Writeup – SANS Holiday Hack Challenge (Part 3 of 4 – Servers)

In this post, we will continue the writeup of the SANS Holiday Hack Challenge, specifically, how we identified the target servers and retrieved the Audio files from each.

Part 4


  • For each of those six items, which vulnerabilities did you discover and exploit?
    • Mobile Analytics Server (via credentialed login access): (none)
    • Dungeon Game: (use the “GDT” function, abuse “DT” to display the win string)
    • Debug Server: (set “verbose”:true in the JSON request)
    • Banner Ad Server: (abuse Meteor’s reliance on the client, HomeQuotes._collection.find().fetch()[4])
    • Uncaught Exception Handler Server: (PHP file inclusion in the “crashdump” parameter in the ReadCrashDump operation)
    • Mobile Analytics Server (post authentication): (forge an admin cookie, modify a saved query to extract data from ‘audio’ table).
  • 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.)
    • Mobile Analytics Server (via credentialed login access): discombobulatedaudio2.mp3
    • Dungeon Game: discombobulatedaudio3.mp3
    • Debug Server: debug-20161224235959-0.mp3
    • Banner Ad Server: discombobulatedaudio5.mp3
    • Uncaught Exception Handler Server: discombobulated-audio-6-XyzE3N9YqKNH.mp3
    • Mobile Analytics Server (post authentication): discombobulatedaudio7.mp3
    • APK: discombobulatedaudio1.mp3

This is an interesting (and lengthy) challenge. The first step of tackling this is to identify the six servers in question. Fortunately, they are all embedded neatly in the resources of the APK, and “apktool” can unpack these resources neatly.

A quick “grep” for “northpolewonderland” through the unpacked res/values folder quickly reveals the location of the servers we are looking for:


From here, we can begin to compromise each of the servers one by one. I will document how I was able to compromise each below.

Analytics (Credentialed Login Access):

This was a trivial “warmup” challenge. Upon accessing https://analytics.northpolewonderland.com, we are presented with a login interface. Authenticating with “guest/busyreindeer78” works, and we are presented with an option to download an MP3, revealing “discombobulatedaudio2.mp3”:



I went for this server next, as one of the NPC’s had disclosed a link to the “dungeon” binary. Upon disassembly of the binary (which nmap revealed to be running on port 11111 of the dungeon.northpolewonderland.com server), this appeared to be a standard text-based RPG, with several debug commands built in. The most interesting command was the “GDT” command, which appeared to unlock a developer mode:


Of note, the “DT” command appeared to allow us to display NPC dialogue and other strings from the game – it would ask us for an entry (an integer), and it would supply whatever string corresponded to that entry in the game’s data store. This quickly revealed an interesting piece of clearly non-standard text:


Emailing this address provides an automated response, with “discombobulatedaudio3.mp3” attached.


The debug server was a JSON endpoint. Initially, sending it “hello world” JSON messages (e.g. {“1″:”2”}) returned nothing, so I went through the Java source code of the APK to identify the parameters I needed to supply:


From here, we can see that the “date”, “udid”, “debug” and “freemem” parameters would usually be sent by the application to the debug server. A quick few minutes of Google later, and we have ourselves a valid request / reply:


On inspection of the response, we note that the “verbose” field is set to false. Setting this to true in the request produces a much more verbose response:


Fetching this file from the web server provides us “debug-20161224235959-0.mp3”.

Banner Ads:

The Banner Ad server revealed a fairly nondescript web interface:


A quick inspection of the source code revealed the use of the Meteor framework. This took me back to an earlier CTF which I had done during the year (I miss which one), where I learned about Meteor’s reliance on client-side controls for security. Josh Owens has an excellent writeup about this here.

Following a hint provided by one of the NPCs, I installed “Meteor Miner” into Chrome, and loaded the site. A little bit of browsing, and I quickly had a meaningful lead:


Using the Chrome developer console, I could then fetch this record and display the “audio” field:


Downloading this file from the web server gave us the “discombobulatedaudio5.mp3” file.

Unhandled Exception Server:

This server was, similar to the “debug” server, another JSON endpoint. Fortunately, this server provides useful feedback, telling you what fields you need to fill to make a valid JSON request. Very quickly, I was able to construct two requests – one to write a “crash dump”, and one to read out the “crash dump”:


Of this request, the most interesting field is “crashdump”. My first approach was to try to read out the “exception.php” file, by setting it to “../exception.php%00”: unfortunately, this produced an HTTP 500 error.

After a little experimentation, I discovered that this was indeed a file inclusion vulnerability, and the php:// filter was allowed. Could the php:// base64 encoding trick be used to encode the “exception.php” file, and read it out?

Indeed it could:


A quick base64 decode later, and we located a comment within the exception.php file, pointing us to “discombobulated-audio-6-XyzE3N9YqKNH.mp3” in the web root.

Mobile Analytics Server (post authentication):

For this challenge, I had a head start – based on the Reddit thread, I knew there had to be a git repository somewhere. I took a guess that the “.git” folder had been left intact on the web server – and I was correct.

Recursively downloading this folder, together with a bit of git checkout magic, I was quickly able to reconstruct the source code to the entire application:”


On reading some of these files, I had realized that only the “administrator” user could access the “/edit.php” functionality. I started by investigating the cookies – it appeared that they were an encoded, encrypted JSON object, containing the username, with the encryption key provided in crypto.php.

I then built a small PHP harness to generate my own cookie:


Substituting this value into the cookie’s “AUTH” field quickly allowed me to log in as an administrator. From here, I had access to the “edit” page:


Initially, I didn’t have an “ID” to use with this page, but then I recalled that I was able to create my own via the “Query” functionality’s option to save a query, as follows:


From here, I could “edit” this request:


Reviewing the source code some more, I found that it was checking for the GET parameters “id” (present), “name” (present), “description” (present) and “query” (not present. Upon further source code review, I realized that I could save arbitrary SQL queries here.

Reviewing the database schema, I was able to identify an “audio” table, which appeared to hold two entries. I could use the TO_BASE64 MySQL function to successfully exfiltrate the second MP3 file, discombobulatedaudio7.mp3:


With all seven MP3 files, we could now proceed to the final parts of the challenge, documented in the next post.

About Norman

Sometimes, I write code. Occasionally, it even works.
This entry was posted in Bards, Computers, Jesting and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.