Wednesday, January 4, 2017

Sans Holiday Challenge 2016

You got to start somewhere

This year the SANS Holiday Challenge had a backstory where Santa Claus himself was kidnapped when he was delivering presents to the children. The only witnesses to the kidnapping were Josh and Jessica Dosis who heard the kidnapping happen. Only clue on the scene was the business card of Santa:

The card has Santa's Twitter handle along with his Instagram id. Both of Santa's accounts were worth examining...

Instagram has a couple of photos and in one of them, you can see a printout of an nmap scan. Too bad only the target domain is shown and not the results:

In the same image there's yet another hint about a ZIP-file needed later:

Combining the two hints, you get the URL to download the zip:

The twitter feed looks weird from the start:

But copying all the tweets and placing them in a file, 1 tweet per row, you find a hidden message:

Let's move on with the story and the questions:

1) What is the secret message in Santa's tweets?

Now that should be easy: Bug Bounty.

2) What is inside the ZIP file distributed by Santa's team?

The zip-file is password protected, but luckily the password is already given to us: "bugbounty". Inside the zip is an Android application package: SantaGram_4.2.apk.

3) What username and password are embedded in the APK file?

To find the username and password, the apk was extracted and converted to jar using dex2jar.
The resulting jar-file was then examined with jd-gui.

A search for the phrase "password" finds the following:


4) What is the name of the audible component (audio file) in the SantaGram APK file?

The audio file is available after you unzip the apk.

Answer: discombobulatedaudio1.mp3
(full path res/raw/discombobulatedaudio1.mp3)

5) What is the password for the "cranpi" account on the Cranberry Pi system?

After running around the game world collecting all the Cranberry Pi pieces we are given an image file ( from Holly Evergreen. After obtaining the image, the first step was mounting it:

First unzip the downloaded zip-file:

Then extract the partitions with 7zip:

This gives us two files: 0.fat and 1.img, where the latter can be directly mounted:

Having access to the /etc/shadow file, what remains is cracking the password for the cranpi user. As suggested by Minty Candicane, John the Ripper together with the RockYou password list is used:

And after a while, the password hash is cracked:

When you give the password to Holly Evergreen, she gives you access to all the terminals around the Northpole.

Answer: yummycookies

6) How did you open each terminal door and where had the villain imprisoned Santa?

The villain had trapped Santa in the past, or more precisely in 1978 (more on getting there later)! He was found in the DFER room.

Yay, Santa:

Now, the terminals. Each terminal gives you a shell access to a linux system (probably a docker container) where you have to perform certain tasks to obtain keys to nearby doors.

Terminal #1

First terminal is in Elf House #2:

Next to a fireplace, cosy :)
The terminal itself is quite helpful as it immediately tells you what you need to do:

Too bad the out.pcap is owned by itchy and no-one else has any permissions to it. Luckily we have some sudo privileges:

We can run tcpdump and strings as itchy, so this pretty much solves the problem of file permissions. The first part of the password is easily found with strings:

The second part didn't open immediately to me but when I noticed that both the users refer to the Simpsons, their dog called "Santa's Little Helper" came to my mind. When I tested that as the password, it worked and I stopped trying to solve the second part.

Terminal #2

There are two terminals in the workshop, one leading to Santa's office and another one leading to the DFER room. The one leading to Santa's office was cracked next.

Again, it's pretty easy to figure out what you are supposed to do:

Executing a simple ls -lahR and reviewing the output reveals something interesting:

The path looks like a pain to escape, so we cheat a bit with find:

Terminal #3

The next terminal was in Santa's Office and it gave you the password for the hidden door in the bookshelf on the left.

When accessing the terminal, you were greeted with a line from the movie "War Games". Continuing the dialog by entering what David Lightman (played by Matthew Broderick) typed in the movie, the dialogue plays out as in the movie and eventually you get the key for the door:

Terminal #4

The next terminal was in the workshop, on the back wall:

Again the goal was clear. This time you were supposed to play (or cheat) a game.

Sometimes cheating takes longer than playing by the rules. After two or three fair games, the Wumpus was killed and the password revealed:

Terminal #5

Final terminal was found in the train yard, on the train (or rather the train-looking time machine):

Accessing the terminal prompts you with a "Train Management Console":

It is possible to control the brakes and view the help document, but when trying to start the train, you are prompted for a password and if you don't have it, your access is denied:

The help document behaves just like less though. If it looks like a duck and it quacks like a duck... Typing "!bash" while viewing the help, brings you to shell:

Viewing the Train_Console file, the password is found and the train can be started:

When you start the train, you see the flux capacitor, but can't change any time settings:

After you exit the train, you are in the past! 1978 to be exact:

If you have opened the doors in present, you get access to them also in the past.


  • The Mobile Analytics Server (via credentialed login access)
  • The Dungeon Game
  • The Debug Server
  • The Banner Ad Server
  • The Uncaught Exception Handler Server
  • The Mobile Analytics Server (post authentication)

For each of those six items, which vulnerabilities did you discover and exploit?

The addresses of each server can be found in the res/values/strings.xml file of the SantaGram apk:
Even the Great Oracle Tom Hessman gave the green light for each of these addresses!

The Mobile Analytics Server (via credentialed login access)

We started by browsing to the analytics server using the URL mentioned earlier. Then we used the credentials found in the apk (guest:busyreindeer78). After logging in, we can directly download an mp3-file from the MP3-link:

The MP3 link ( in the top of the page allows you to download an mp3-file named discombobulatedaudio2.mp3.

That was pretty straightforward :)

Status: we have 2 audio files (remember that the first one was found for question 4).

The Dungeon Game

Pepper Minstix offers you a local copy of an older version of the game.

After playing around with it for a while we discovered a hidden menu. At first the hidden menu was accessed by running the game in a debugger (gdb), setting a breakpoint to just after a call to strcmp and then changing the return value (eax/rax) to 0. However, looking at the arguments passed to strcmp using the gdb-peda extension, it turns out that it is possible to enter the debug menu by simply typing "GDT" in the game.

Below is an image of the "debug command check", with a breakpoint set to the row where the call to strcmp is made. The first argument, arg[0], is set to the user typed command ("L"), and the second argument is the expected value for entering the debug menu ("GDT").

After typing "GDT" instead of "L", the debug menu is indeed presented within the game:

As an alternative to finding the debug menu with gdb, one could have also read the source code. :)

After examining rooms with the DR (Display ROOMS) and D2 (Display ROOM2) commands, we find that the last two rooms are different from the others. D2 doesn't even seem to find them at all. Using the AH (Alter Here) command and entering the second-to-last room number, we arrive at north pole:

Moving north brings us to "the elf":

The elf wants to trade something for his information. luckily the GDT-menu also has a TK (Take) command, which allows us to obtain items. To find the correct item was a simple case of testing...

Giving the coins to the elf, the game ends, pointing us towards an online version for the "true prize":

A not too far fetched guess is that the online version is probably on the server. Port 80 hosts a static about page, which does not seem interesting to us. A simple nmap scan yields no results other than the standard ports 80 (http) and 22 (ssh). Neither seem to provide us with the information we need. Then we remember the hint from Misty Candycane:

When we instead performed a syn scan against the dungeon server with the full port range, we found an open TCP port 11111. We then connected to the port using netcat and we found a familiar prompt. We had found the online version of the dungeon game!

Now that we know about the debug menu (GDT) as well as the correct room (192) and item id (25), the game is over pretty quickly:

With our newly obtained knowledge, we craft a letter to Santa Peppermint and get a lovely response:

Status: we have 3 audio files.

The Debug Server

Also the debug url was found in the apk ( To get a better idea about what the server expects us to send to it, the jar file (as previously extracted using the dex2jar tool) was again used. When examining the jar-file using jd-gui, it was found that the debug server url was used in the EditProfile class. Here's the construction of the json object that is later sent to said debug url:

Only 4 parameters in a json call, it should be simple to craft a json file and send it with curl. After a bit of testing, such a request was created that the server replied:

The response:

Notice that in the response there is a property called "verbose" on the "request" object, even though that property was never specified in the actual request. Crafting a similar request as before, but this time adding "verbose":true to it and we get a different response:

The first item in the files array is an mp3 file, which we were able to download from

Status: we have 4 audio files.

The Banner Ad Server

Again the ad server url is found in the apk:

When we viewed the page source, it became obvious that it's made with meteor
The hints from Pepper Minstix were invaluable here:

We started by checking all the routes. This was simple with Chrome's javascript console:

Looking at each of them, the last one (always the last one) acts a bit differently... It seems to load some data before telling us that we are not allowed, as opposed to saying we are not allowed directly like all the other routes do. Investigating the websocket frames, there is one extra entry here that should have probably never been pushed to any non-authenticated clients (sorry about the small image size, just click it to see the original):

Embedded in an extra field we find that the audio file is at:

Status: we have 5 audio files.

The Uncaught Exception Handler Server

Also the URL for Exception Handler Server is in the apk. The exception handler server url is referenced in the SplashScreen and again we examine the Java code to figure out what should be sent to the server. Part of the decompiled Java code is here:

Basically we have two JSON objects where the first contain only a few properties and the second one is sent as the data property of the first one. When we invoke the WriteCrashDump operation, the server stores anything we write to php-files. Unluckily for us, nothing in those php files gets executed. Testing the server further, an empty operation was sent, which gave us the following response:

This moved our focus to the ReadCrashDump operation. We were able to read our crash dumps and thought that there must be a Local File Inclusion (LFI) vulnerability, but didn't get much further, until we remembered the hint from Sugarplum Mary:

This means that if there really is an LFI, we should be able to read also PHP-files without the target server parsing them, thus giving us the PHP source. A successful exploit is shown here:

Looks promising. When we then decode the base64-encoded text, we find something interesting:

When we then take note of the comment, we proceed to download the audio file from

Status: we have 6 audio files. Only 1 more to go

The Mobile Analytics Server (post authentication)

This was the trickiest of the bunch in my opinion, but again the hints from the elves were helpful:

When we ran nmap against the analytics server with the -sC switch, the following was a part of the output:

When we check the .git folder, we find that it has directory indexing on:

Because the directory indexing is on, we can download all the files quite easily using wget and it's mirroring capabilities:

This took a while to complete but after a couple of minutes of patient waiting we had downloaded the ".git" folder and its subfolders. We had the following structure:

Now we can checkout all the files in the .git repository using the git checkout command:

And let's not forget the commit history. Executing git log, we get a full commit history, including comments. The following commit seemed interesting, after all: what unnecessary data could there be in the database dump:

How does the admin password sound? It's surprisingly common to find passwords or keys in any version control system and this isn't an exception. Have a look at the following diff and take a note of the removed line (the one in red):

Luckily for us, the administrator password wasn't changed and we were able to log in with it. The user interface was a bit different than what it was for the guest:

This time we don't get the option to download the audio file, but we have something called "Edit" instead. Since we now have the full source at our disposal (from the git repository, remember?) we assume that this is a bit more complicated than the previous levels.

The Edit-link brings us to edit.php, which allows the user to modify the metadata of an existing saved report. The saved reports actually store the SQL clauses used for generating them to the database on a column called query, probably as a way to allow reports to be "updated" as the underlying data changes. The table for storing saved reports looks as follows:

The edit.php has a peculiar way to handle the data submitted from the form:

While this works, it also allows us to modify other columns than name and description, including the column 'query'. Additionally, due to how the report stores and executes sql statements, any SQL statement we put in the column query will be executed when the saved report is viewed. 

To exploit this vulnerability, we first need to create a saved report (remember to save the query):

We then get a link to our saved report and when we click it, we are taken to view.php and shown the saved report, including the metadata (ID, Name and Details):

With this ID we can then use the Edit-functionality and update the metadata. What we really want to do, is to change the column query instead of description, thus we modify the form with Chrome's developer tools:

The name attribute was "description" but now it's "query". 

So, what do we want from the database? Since we are still interested about the audio files, the table audio seems like a reasonable place to start. Here's the structure of the table audio:

The first attempt was to simply select all the rows and columns from the audio-table

And then we return to view.php and see the following page:

So, we get the metadata from the files, but not the actual files itself. We then thought that we could use the same method as we did as guest, since we now know the file id. However, it turns out that the download is disabled for administrator, as can be seen from the php code:

So we have to think of something else. It's normal that you don't get binary data (any blobs) when executing select clauses, so perhaps we want to convert it to something else... Two obvious choices are hex and base64 and we decided to use the latter. We modify the query a bit (again change the name of the field):

Then go back to the view.php and view the page source, to get the nice formatting:

Then we proceed to copy the base64 encoded data to a local file and decode it:
Status: we have 7 audio files. That's all of them!

8) What are the names of the audio files you discovered from each system above? There are a total of SEVEN audio files (one from the original APK in Question 4, plus one for each of the six items in the bullet list above.)

  • discombobulatedaudio1.mp3 - source: SantaGram_4.2.apk
  • discombobulatedaudio2.mp3 - source:
  • discombobulatedaudio3.mp3 - source: email from
  • debug-20161224235959-0.mp3 - source:
  • discombobulatedaudio5.mp3 - source:
  • discombobulated-audio-6-XyzE3N9YqKNH.mp3 -
  • discombobulatedaudio7.mp3 - source: database of the analytics -server

9) Who is the villain behind the nefarious plot.

To find the villain, we need to analyze the audio files. 

First step was renaming two files to make things easier: 
  • debug-20161224235959-0.mp3 to discombobulatedaudio4.mp3 and
  • discombobulated-audio-6-XyzE3N9YqKNH.mp3 to discombobulatedaudio6.mp3

The seven files were then combined (or concatenated) to one using SoX:

SoX has multiple effects to play with:

The first attempt was made by changing the speed, but it wasn't until we tried to altering the tempo that we actually got a result. When the tempo was raised to about 5 times faster, we were able to hear the mangled message. It said:
Father Christmas, Santa Claus. Or, as I've always known him, Jeff.
This is a reference to Dr. Who episode "A Christmas Carol" (check also

The message from audio files was accepted as the key to the final door. You just had to have correct capitalization and punctuation. 

So, the villain of the story was Dr. Who!

10) Why had the villain abducted Santa?

Let's allow the good Doctor to explain himself:

Oh no! So it's our fault that we still have to live with Star Wars Christmas Special!

The End

After we've talked with the Doctor, ending credits roll.