How to get Tomorrowland tickets - A technical analysis en

By Gtoniser on Monday 6 February 2017 10:27 - Comments (10)
Category: Algemeen, Views: 6.455

Introduction
Tomorrowland - Every year over a million people (as the organisation claims) try to obtain tickets for this 3-day festival in Belgium.
Since the amount of tickets is considerably lower than the number of people interested, many people leave disappointed after the ticket sale every year.
This blogpost explores the technique used by Paylogic, the payment provider for the Tomorrowland tickets, to sell the tickets in a scalable way.
It also shows how this system can be scripted/abused to increase your chance of buying tickets.

The process
So how does the normal process for getting tickets look? There are 3 steps:
  1. You preregister before the sale of the event starts
  2. On the day of the event, you open your personal link, and wait in the queue for a chance to buy tickets
  3. When you're lucky, you get through the queue to buy tickets.
Step 1 - Preregistration
Preregistering before the event gives us a unique link that can be used to buy tickets.
The link looks something like this:
https://worldwide-ticket-sale.tomorrowland.com/?AnalyticsID=UA-37589046-1&#pld=eJxNjksOwjAMRK9SZQ0oLX9WFLFCwBUi0xgalE-VuBIV4u7UYYPlzbzxWPMWXRs8Kt-7G0axK4Qsq_liuVpvtmJSiMbQwLR2iTBqcAzvJiZSHhyydQqtZ2rhDx4DMnug17-3JcsuJAKrmqDzUTlOfWADtI6YEsPLkCgiUpETNxOpVRooByop5VSW4-ZuofcUc73rmQE6MJblc6y0xxe4zuKsCU58viYmRGI=


The interesting part here is the #pld which follows the link, which is unique for every person. Because this part follows after the # sign, it is not sent to the server when the page is requested.
It is thus safe to say that the server does not check the pld link provided. When we look at the javascript on the page, we can see that the information is decoded and processed by the script. Because of the characters used, it is easy to spot that the data is base64 encoded.
The javascript on the page (at least the Belgian sale page) in turn loads a library used for compressing and decompressing data. So we assume that the data is compressed and base64 encoded. Lets see what a little python does with it:

Python:
1
2
3
4
5
import zlib
import base64
pld = 'eJxNztsKwjAMBuBXGb1WaefZKx0TRPAZSlzjVulhtB04xHd3qTeG3ORLCP-b9Z13KN1g7xjYoWBclMvVerPd7dmsYI1OI2mNrrgAtGQPHWKSDizS5uo7R2rgD2uPZC069fsqaOx9TGBk41U-ElOdKlqAUgFjJLyNMQXERHzXIXVSQcrnJed8zsXUOZgfXAo5W3UmQAva0PicAh3xBbY3uGi8ZZ8v7-xDCA=='
regdata = zlib.decompress(base64.b64decode(pld,"-_"))
print regdata


This gives the following result:

{"phone_number": "0123456789", "city": "Amsterdam", "first_name": "John", "last_name": "Doe", "gender": "1", "postal_code": "1111AB", "address": "Mystreet 1", "birth_date": "2000-01-01", "country": "NL", "email": "john@example.com"}

Ah, so the personal data is just a JSON object with the information that you entered at registration. It is also possible to change the JSON, use that in the URL and still enter the sale. In fact, it is also possible to buy tickets for different events with this same snippet.
The data is just passed through to the Paylogic store website, after which it will be used to pre-fill your data when purchasing tickets. The event does not matter, since the same sale system is used. This also suggest that preregistration is maybe not even required to get a ticket.

Step 2 - The sale itself
On the day of the sale itself you can visit the sale page with the unique link, which will put you in the queue around the event start time. Because of the ticket demand, there are a lot of myths on the internet from what you should do to maximize your chance.
Note that the information here is the result of my personal analysis of the Paylogic queue system, and is partly based on observations and reading (obfuscated) javascript, meaning that some things may not be 100% correct.

The queue system itself is quite simple. Lets look at the URL itself (which gets loaded via an iframe on the landing page) first:
https://queue.paylogic.com/115642/2993/?AnalyticsUID=UA-37589046-1


We see the same Google Analytics ID as we saw in the previous URL. This is used by Paylogic to see how well their system performs.
The other two interesting variables are the two numbers in the URL, 115642 and 2993. The 115642 is the event ID for which you will be queuing up. Both the Belgian, worldwide presale and the worldwide regular sale had different event IDs.
The second number, 2993, seems to be the same for all events and across years, indicating it is probably a merchant ID for the Tomorrowland organization (Paylogic calls it the point_of_sale_id).

Once on the page, the queue system is handled via Javascript, doing regular AJAX requests to the Paylogic Queue API. The URL for this API is
https://queue-api.paylogic.com/json/115642/2993/

Here we see the same IDs that were used previously, for the event ID and point_of_sale ID.

The queue API is used to handle the thousands of people trying to get tickets at the same time, which is probably why Paylogic tried to keep it as simple as possible.

Upon loading the page, your browser will set a timer with a random time before it will contact the API server. Once the event starts, this API server will start handing out tokens. Lets call this server the "token server".
A request to the token server occurs via AJAX, to for example the following URL:
https://queue-api.paylogic.com/json/115642/2993/?now=1486231200195

We see once again the two sale IDs, and an added timestamp to prevent the browser from caching the request.
The result of this is the following JSON:
{"content": {"announcements": [], "locale": "en", "enabled_languages": ["en"], "not_started_page": {"en": "<h2>The Tomorrowland WorldWide Ticket Sale has not started yet.</h2>\r\n<p><span style=\"font-weight: 400;\">The Worldwide Ticket Sale for Tomorrowland 2017 starts February 4</span><span style=\"font-weight: 400;\">th</span><span style=\"font-weight: 400;\">, 17h00 (CET).</span></p>"}, "active_page_name": "sold_out", "active_page": {"en": "<h2><strong>Tomorrowland 2017 is Sold Out</strong></h2>\r\n<p>Your love for Tomorrowland was phenomenal</p>\r\n<p><a href=\"https://shop.globaljourney.com\" target=\"_blank\">Limited number of Global Journey Travel Packages are still available</a></p>\r\n<p>Go to <a href=\"http://shop.globaljourney.com\" target=\"_blank\">shop.globaljourney.com</a></p>"}}, "start_date": "2017-02-04T17:00:00+01:00", "redirect": null, "refresh_seconds": null, "token": null}

We see several variables here, the fist one being the content, which contains relevant content to fill in the templates on the site and announcements regarding the sale.
For our purpose, this variable is not really interesting. The following variables, start_date, redirect, refresh_seconds and token, are much more interesting.
The token is your queue ticket. In the example above it is not present because at this point the tickets were already sold out. During the sale, the token looks something like this:
1ca2l9+0+115642+2993+81672+66+1486227779+1486227853+8ce0c64da3a8402b9c64435573ac3a32+1ca3od+66+p-RibtHJPN76UvZQMS_iVCFfoYHTOdEX0zsitA==

We see several strings and numbers, separated by plus signs. Once again we see the sale IDs, some numbers and some strings, one 32 characters long (maybe a hash?), and one seemingly base64 encoded.
The numbers are the most interesting in the token. The 1486227779 and 1486227853 are UNIX timestamps (measured in seconds since 1 Jan 1970), the first one is from 2017-02-04 18:02:59 CET, while the second one is from 18:04:13.
My guess is that these timestamps indicate the time that the token is valid. Since this time is pretty short, your browser performs a new API request after the number of seconds indicated by the refresh_seconds variable discussed earlier, to update the token.
I haven't figured out what the number 66 stands for, but I've found the number 81672 in this token to be increasing when new tokens are requested during the sale. This number most likely represents your position in the queue, which in this case is 81672. Lastly, the base64 encoded string does not appear to decode to readable text. I'm guessing its a HMAC used to sign the token, so that the server can verify it hasn't been changed.
One thing to note here is that the personal information is never sent to the server during the queuing time (and is thus not verified or required to get a token).

Your browser will store the token in a cookie, and will send this cookie in the next request (both as cookie and as part of the URL). After every request, you get a new token, with a new refresh time, while your position in the queue remains the same (you can't see how many people are in front of you still, you can just see what your absolute position in the queue since the start is).

Step 3 - Buying your tickets
Once it is your turn to buy tickets, the "redirect" variable will be set, which contains a URL to https://frontoffice.paylogic.nl, which is the main Paylogic ticket site, where you can choose your tickets and pay for them.
The url looks like this:
https://frontoffice.paylogic.nl/?token=1ca2ks%2B1%2B115642%2B2993%2B17226%2B66%2B1486226137%2B1486226137%2Ba44d6867023e4e1c95e675e5c5970da4%2B1ca3O9%2B63%2B0_ta34ptPis4RchYM7RugipZVFYFlqSyR4kfRg%3D%3D&event_id=115642&point_of_sale_id=2993&pld=eJxNztsKwjAMBuBXGb1WaefZKx0TRPAZSlzjVulhtB04xHd3qTeG3ORLCP-b9Z13KN1g7xjYoWBclMvVerPd7dmsYI1OI2mNrrgAtGQPHWKSDizS5uo7R2rgD2uPZC069fsqaOx9TGBk41U-ElOdKlqAUgFjJLyNMQXERHzXIXVSQcrnJed8zsXUOZgfXAo5W3UmQAva0PicAh3xBbY3uGi8ZZ8v7-xDCA==


We see once again the token (with all the special characters encoded), though now the number 0 before the 11564 is changed to a 1, which could indicate that we are now authorized to buy tickets. At the end we see the same Paylogic data as previously, the first time our personal data is sent to the server.

Now we understand how the system works, we also understand how it can be abused. What I haven't mentioned yet, are a few rules that apply to the token server:
  • If you try refresh your token before the refresh_seconds time, it will be invalidated (this happens when you open multiple tabs with the ticket page).
  • When the sale starts, tokens with queue position 0 are given out by the token server. These tokens are most likely there to fool scripts, and cannot be used to buy tickets.
  • Making changes to your token, for example to the queue position, will make it invalid
Because of how the system works, there are several ways that can abuse the ticket system:
  • Opening multiple browsers or incognito windows will give you multiple chances to buy a ticket.
  • Writing a script that requests tokens around the time the sale will start and refreshes those in the same way a browser would allows for automation of the queue system.
Note that refreshing the browser page at a fixed time will not work, since both the start of the sale and the time your browser will take to request its first ticket are random (the sale does not start exactly at the time they say it does, and a few seconds makes all the difference).

As a proof of concept, I've developed a simple python script that will do the following:
  • A few minutes prior to the event, it will start requesting tokens from the server
  • Once the event starts, it will discard tokens that do not have a queue position (position 0)
  • Once valid tokens are obtained, the script will refresh the tokens at the correct times. The script will then wait until it gets a link to the shop page to buy tickets.
This approach seems to work fairly well. During the international sale, I was able to get a link to the ticket shop using this approach, with only 10 threads that would request tokens. I didn't actually buy any tickets, the point was to prove it is possible.
With more threads, during the presale (during which I think more tickets were available), or as a Belgian person during the Belgian sale, I imagine that it would be not that hard to purchase any type of tickets you could want.

Obtaining a token:
https://tweakers.net/ext/f/CZ9n3zwcH9EAGYDiv5EaKRnj/full.png

Getting through the queue:
https://tweakers.net/ext/f/IWb8ZyG0mO7XFTptTyRVmlkV/full.png

The ticket shop:
https://tweakers.net/ext/f/dQNS9ovK1aSoOLFsIef8GE7u/full.png

Conclusions and recommendations
With the current system that Paylogic uses it is not too complex to script the queue system and abuse this to buy tickets in an automated way. I imagine resellers have been doing this already for a couple of years (I haven't noticed any significant changes in the way the API operates since the Tomorrowland sale in 2015).
The best way to prevent this would be encrypting the entire token payload, so that the queue position cannot be read or automated by anyone that attempts to abuse the system.
This together with the queue position 0 should prevent most automated attacks and make the sale (more) fair for everyone. Of course this would not prevent people from just opening more browser windows.
IP restrictions and request rate limiting (for as far as this is not yet in place) may help preventing these attacks. Another option is enforcing the checks of the preregistration data. While it is against the official rules to use the same shop link multiple times, this does not seem to be technically enforced in any way (the personal data is not even sent to the server before you have the chance to buy tickets).

Volgende: Wachtwoorden hashen? Wettelijk verplicht! 08-'14 Wachtwoorden hashen? Wettelijk verplicht!

Comments


By Tweakers user masauri, Sunday 5 February 2017 19:21

Boeiend om te lezen, ben er zelf niet in geslaagd tickets te kopen dus helaas.
Maar kan me indenken dat deze technieken idd al jaren gebruikt worden om misbruikt te worden.
Wat me verbaasd is dat de persoonlijke link gewoon nergens voor gebruikt word!
Thx voor de info!

By Tweakers user Blokker_1999, Sunday 5 February 2017 20:40

masauri wrote on Sunday 5 February 2017 @ 19:21:
Boeiend om te lezen, ben er zelf niet in geslaagd tickets te kopen dus helaas.
Maar kan me indenken dat deze technieken idd al jaren gebruikt worden om misbruikt te worden.
Wat me verbaasd is dat de persoonlijke link gewoon nergens voor gebruikt word!
Thx voor de info!
De pre registratie is simpelweg een mechanisme om een inschatting te kunnen maken van de drukte op de servers bij de ticket verkoop. Zo weet men bij benadering hoeveel extra compute power ze moeten inhuren bij de cloud aanbieder.

By Tweakers user GrooV, Monday 6 February 2017 07:59

Blokker_1999 wrote on Sunday 5 February 2017 @ 20:40:
[...]
De pre registratie is simpelweg een mechanisme om een inschatting te kunnen maken van de drukte op de servers bij de ticket verkoop. Zo weet men bij benadering hoeveel extra compute power ze moeten inhuren bij de cloud aanbieder.
Als je het goed hebt ingeregeld gebeurt de scaling automatisch natuurlijk. Denk niet dat Paylogic dit gaat apart gaat inhuren

By Tweakers user kwdr, Monday 6 February 2017 09:54

Nette analyse!

By Tweakers user JT, Monday 6 February 2017 10:14

Leuke analyse :)

By Tweakers user Marc Rademaker, Monday 6 February 2017 11:28

Erg interessant, ook om te weten dat ze dus niet daadwerkelijk om 17.00 stipt beginnen (ik dacht dat scriptmatig precies op het juiste moment inloggen zou helpen met hoog in de queue terechtkomen).

Misschien ook interessant, is dat ze dit in de VS gaan verbieden, al is het wel de vraag hoe je dit gaat 'enforcen': https://arstechnica.com/t...n-ticket-buying-software/

By Tweakers user ironman73, Monday 6 February 2017 20:01

Interresante materie!

By Tweakers user Ghanghis, Wednesday 8 February 2017 11:44

Tof om te lezen. Mooi gedaan.

By Tweakers user MM, Wednesday 8 February 2017 16:39

Marc Rademaker wrote on Monday 6 February 2017 @ 11:28:
Erg interessant, ook om te weten dat ze dus niet daadwerkelijk om 17.00 stipt beginnen (ik dacht dat scriptmatig precies op het juiste moment inloggen zou helpen met hoog in de queue terechtkomen).

Misschien ook interessant, is dat ze dit in de VS gaan verbieden, al is het wel de vraag hoe je dit gaat 'enforcen': https://arstechnica.com/t...n-ticket-buying-software/
Geen populair statement, maar desondanks:
Meer vraag dan aanbod... economisch gezien maar één juiste reactie: prijs omhoog. Anders ga je dit soort praktijken van resellen blijven tegenkomen...

Laat iedereen bieden wat ze ervoor over hebben en na een vaste tijd (week?) mogen de 100.000 meest biedenden naar het event voor de prijs die ze geboden hebben :)
Soms ben je dan duurder uit dan in het oude systeem als je persé wilt gaan, maar het mes snijdt aan twee kanten. Je kunt ook inschrijven bij evenementen voor een laag bedrag in de hoop dat er nog kaartjes beschikbaar zijn voor die prijs.

By Tweakers user stftweaker, Friday 10 February 2017 10:08

How can i get the script ? What a wonderfull life no more stress no more waiting :D Wat zou dat een uitkomst zijn zeg.

Comments are closed