Monthly Archives: December 2012

CTF Writeup: SANS Holiday Challenge 2012

The details for this challenge are here.  However, the basics are the following:

  • Move from Zone 0 to 5 at this page and this page.
  • There are also twitter accounts for @sn0w_m1s3r and @h34t_m1s3r that are necessary to complete the competition.
  • The flags are left as HTML comments at the end of the page.

Heat Miser

Zone 0

Flag: 1732bcff12e6550ff9ea44d594001418

Both Heat Miser and Snow Miser’s home pages mentioned something about blocking search engines from accessing Zone 1.  One way to do this is by adding a robots.txt file.  Open the file up, and you’ll see it includes the URL to Zone 1.


Zone 1

Flag: d8c94233daef256c42bb95bd61382e02

The page says the link to Zone 2 was temporarily removed.  If you view the source of the page, you’ll see the link was simply commented out, but still clearly visible in the HTML source.

HTML source

Zone 2

Flag: ef963731de7e886226fe4a6a6c2971f1

On this page, we get part of the URL to Zone 3.  On December 6 at 6:03 PM, Heat Miser posts an image to twitter of him loading up a metasploit exploit.  However, you can see his metasploit window is partially transparent (as hinted by Snow Miser on twitter), with the last portion of the Zone 3 URL barely visible.  Some finessing with the contrast, saturation, and exposure of the image makes the URL visible enough to use.

Zone 3

Flag: 0d524fb8d8f9f88eb9da5b286661a824

There is a link readily available to Zone 4 on this page (on the sidebar).  However, when you click on the link, you get redirected to noaccess.php.  This is when you fire up your trusty proxy (such as Burp) and try again.

Burp Proxy

This time you’ll notice that although there is a redirect, the entire content for index.php is still there. This is what happens in PHP when you add a redirect header without using the exit() or die() command afterwards (as shown by the twitter hint given by Snow Miser and his meme).  Question 4 on the competition welcome page suggests there may be a coding error to solve this problem, so that must be it.

To view the page like normal, change the first line from 302 Found to 200 OK, and then remove the Location line (it also works to remove the header entirely).  Then forward on your modified HTML and you’ll see the text of Zone 4.

Zone 4

Flag: e3ae414e6d428c3b0c7cff03783e305f

This page contains the link to Zone 5 as part of the text.  However, just like Zone 4, you get redirected to noaccess.php.  Fire up your proxy again, and you’ll notice two things.  First, index.php is redirecting you to noaccess.php.  Second, it is additionally giving you a browser cookie as it does so (UID=b8c37e33defde51cf91e1e03e51657da).  Question 5 on the competition welcome page also hints at using a browser cookie to solve this problem.


Often times the best password cracker is Google.  So paste b8c37e33defde51cf91e1e03e51657da into Google, and sure enough you are quickly told that the cookie that is being set is the md5 value of 1001 (again, you get a bit of a hint at this on a tweet from Snow Miser).

1001 sounds like a lower level, unprivileged account number.  We want the highest level administrative privileges, which is usually given to user number 1.  So instead of getting the cookie with the md5 of 1001, change it so you are getting the cookie with the md5 of 1 (c4ca4238a0b923820dcc509a6f75849b) and click Forward.  You’ll still be forwarded to noaccess.php, but this time a different cookie got set.  Return to index.php, and you are given full access without a redirect because you present yourself as user 1 instead of user 1001.

Zone 5

Flag: f478c549e37fa33467241d847f862e6f

Click to disable the heater, and suddenly Southtown is plunged into a bitter cold.  Congrats!heat_zone5

Snow Miser

Zone 0

Flag: 3b5a630fc67251aa5555f4979787c93f

Similar to Heat Miser’s zone 2 page, here we get part of the URL to Zone 1.  On December 6 at 5:50 PM, Snow Miser posts an image to twitter of him “chilling out” with a drink.  However, you can see a reflection on the glass (as hinted by Heat Miser on twitter), with the last portion of the Zone 1 URL.  You’ll need to flip the image a couple times to turn the reflection the right way to face you, as well as sharpen it, but you eventually get a clear enough view to move on to Zone 1.

Zone 1

Flag: 38bef0b61ba8edda377b626fe6708bfa

This page mentions the URL to zone 2 can be found by analyzing the images on the page.  Question 2 on the competition welcome page mentions using steghide to solve this problem, so we must be looking for an image with steganography embedded.

Click the enable button, and you have the on.png image presented.  Click the disable button, and you are presented with the off.jpg image.  Every other image on the site is a png except this one.  Also, while the steghide software doesn’t support png files, it does support jpg files.  This must be the right image.

In order to find the key to unlock the hidden text, run strings on the file to search for something that looks like a password.

snow_zone1You quickly find the IceIceBaby! text (as it turns out, this is actually in the meta data as the Comments for the jpg).  Finally, run the steghide software with the right key, and tmpfile.txt gets extracted with the URL to Zone 2.


Zone 2

Flag: b8231c2bac801b54f732cfbdcd7e47b7

Similar to zone 0, this page offers part of the link to zone 3, but not the entire thing.  The full link to zone 3 is actually in a data dump from Snow Miser’s android device that Heat Miser posted on twitter.  After extracting the data, grepping for the word “zone” reveals a number of files where the location is stored, particularly in the browser cache.

snow_zone2The file data/data/ actually contains a cache of the Zone 3 HTML source, which includes the URL.

Zone 3

Flag: 08ba610172aade5d1c8ea738013a2e99

This page is an encryption problem.  It contains the plaintext and the ciphertext for an old Zone 4 URL, as well as the ciphertext for the new Zone 4 URL, encrypted using the same key as before.

The ciphertext is twice the size of the plaintext, and only contains A-F and 0-9.  Therefore it is a good assumption that we are dealing with some sort of stream cipher that gets converted to hexadecimal (since there are 2 hex characters for every 1 ascii character).  A simple stream cipher is to simply XOR a plaintext with a key that is the same size as your plaintext.  Using XOR would make sense given the hint from question 3 on the competition welcome page.

The good news with that is that due to the properties of XOR, you can come up with the key given a plaintext and ciphertext.  In other words, if A xor B = C, then A xor C = B as well.  So a PHP script was written to test the theory as follows:

$plaintext1 = ‘zone-4-F7677DA8-3D77-11E2-BB65-E4BF6188709B';
$ciphertext1 = ’20d916c6c29ee53c30ea1effc63b1c72147eb86b998a25c0cf1bf66939e8621b3132d83abb1683df619238′;
$ciphertext2 = ’20d916c6c29ee54343e81ff1b14c1372650cbf19998f51b5c51bf66f49ec62184034a94fc9198fa9179849′;

// convert from hex to ascii and get the key from the old zone 4 URL
$key = $plaintext1 ^ hextoascii($ciphertext1);

// use the key to get the plaintext from the ciphertext of the new zone 4 URL
$plaintext2 = $key ^ hextoascii($ciphertext2);

echo “The new zone 4 URL is $plaintext2″;

Assuming you have written a function to convert hex to ascii, this will give you the URL to zone 4.

Zone 4

Flag: de32b158f102a60aba7de3ee8d5d265a

This page tells you that in order to access Zone 5, you need the correct one time password.  It also mentions svn 1.7 is used to update Zone 5.  If you enter the wrong password, it takes you to noaccess.php under zone 5.  Heat Miser tweeted about a vulnerability in that version of svn, along with a link to a writeup for how to exploit the vulnerability.

Following the instructions of the writeup, you can verify that Zone 5 is vulnerable by grabbing the .svn/wc.db file with wget, and move on to grab the source code of index.php and noaccess.php after reading the location of their source code under the svn database.


With the source code, you can copy the generate_otp function from index.php to generate your own one time password.  The only problem is to get the same time as the server to give to the generate_otp function, but the noaccess.php file conveniently prints that time out in an HTML comment each time you go to it.  With the correct one time password, you are in with full access to zone 5.

Zone 5

Flag: 3ab1c5fa327343721bc798f116be8dc6

Click disable, and the North Pole is suddenly on fire!



  1. Where did you find the remainder of Snow Miser’s Zone 1 URL?
    From the reflection on the glass in the image that Snow Miser tweeted.
  2. What is the key you used with steghide to extract Snow Miser’s Zone 2 URL? Where did you find the key?
    IceIceBaby! found while running strings on the off.jpg image.
  3. On Snow Miser’s Zone 3 page, why is using the same key multiple times a bad idea?
    If somebody somehow gets the key for any old message, then that person can decrypt any message sent in the future using the same key.
  4. What was the coding error in Zone 4 of Heat Miser’s site that allowed you to find the URL for Zone 5?
    The PHP page did not exit() or die() after adding a header redirect to the page, allowing the original page to be transferred before the redirect took place.
  5. How did you manipulate the cookie to get to Zone 5 of Heat Miser’s Control System?
    There are any number of ways to manipulate a cookie, particularly with various Firefox extensions.  I used a proxy to change the cookie information before it reached my browser.
  6. Please briefly describe the process, steps, and tools you used to conquer each zone, including all of the flags hidden in the comments of each zone page.
    See above.