Sunday, 22 January 2017

SANS Holiday Hack Challenge 2016 Write-Up (Part 2)

This is part two of my write-up to SANS' Holiday Hack Challenge 2016.

Part 1 can be found here.

Part 4: My Gosh... It's Full of Holes

Part 4 is mainly about finding and exploiting the systems mentioned below. From the endeavors before I had the APK and the dungeon game. I decided to go with the APK first because while answering some of the questions before, I found some clues that hinted for communication.

The Mobile Analytics Server (via credentialed login access)


In order to capture some communications I used Genymotion to run the APK, I had it configured to use a bridged interface for network communication, this made it easier to filter traffic later on. I used wireshark initially and found what I was looking for.


SantaGram is communicating to analytics.northpolewonderland.com (104.198.252.157) which I made sure is in scope. The communication is encrypted so first thing was to surf to the domain using my browser.

If you recall question number three, there are credentials stored in the APK and I extracted them from a method called postDeviceAnalyticsData() - so chances are good they will work here too.

And they did, conveniently from here the mp3 in question was only one click away. Second part of the puzzle! discombobulatedaudio2.mp3


The Banner Ad Server


I decided to stick with the order in which I solved the hosts, rather than sticking with the order of the questions.
I was able to identify this server's address from the traffic capture of my emulated Android device running SantaGram as well.


The target therefore is ads.northpolewonderland.com (104.198.221.240) which again, I made sure is in scope via the helpful Elf.

Again opening the website in my browser was the first step I took. With the help of wappalyzer I quickly figured that the website is running Meteor


However, one clould also easily figure this out by looking at the source code, which would reveal this:

<script type="text/javascript">__meteor_runtime_config__ = JSON.parse(decodeURIComponent("%7B%22meteorRelease%22%3A%22METEOR%401.4.2.3%22%2C%22meteorEnv%22%3A%7B%22NODE_ENV%22%3A%22production%22%2C%22TEST_METADATA%22%3A%22%7B%7D%22%7D%2C%22PUBLIC_SETTINGS%22%3A%7B%7D%2C%22ROOT_URL%22%3A%22http%3A%2F%2Fads.northpolewonderland.com%22%2C%22ROOT_URL_PATH_PREFIX%22%3A%22%22%2C%22appId%22%3A%221vgh1e61x7h692h4hyt1%22%2C%22autoupdateVersion%22%3A%22537dcf6b4594db16ea2d99d0a920f2deeb7dc9f1%22%2C%22autoupdateVersionRefreshable%22%3A%2205c3f7dba9f3e15efa3d971acf18cab901dc0505%22%2C%22autoupdateVersionCordova%22%3A%22none%22%7D"));</script>

Recalling the hint by some Elf about hacking Meteor was really helpful for this challenge. The Elf Pepper Mintstix basically tells you to check out a blog post which gives you a basic wrap up about Meteor and common ways to attack it - if configured in a bad way.

I simply did what the blog post suggested, I installed the tampermonkey script Meteor Miner and reloaded the website.



The blog post very specifically tells you that Routes are used to navigate between pages. There are many routes for the given webpage, with pages the user could not access from the website itself. However for most of these sites one would need credentials.
One other fact the blog post is talking a lot about are collections. These are basically data fields which are used by the application to store data. 
While navigating through the pages I simply watched the collections part of Meteor Miner until something was displayed there. Then I looked through all nodes if there would be something of interest. 

This is the case for two routes, the main webpage / and then /admin/quotes which I do not have access too. However it still lists 5 collections. Those can be retrieved by a call to the corresponding JavaScript function from the browsers console. The collection's name is HomeQuotes therefore the function to query this collection is HomeQuotes.find().fetch().



The last entry of this collection is a link to the mp3 file I was looking for. Puzzle piece number five successfully acquired. 

Finding the rest of the servers


At this point I only observed traffic to the two systems already exploited. However I was not able to see any further traffic. I was a little desperate at that point and used a tool which I would use at work if i need some additional information - passivetotal. This obviously showed me all the hosts which are missing, but I felt like I've cheated and so I went back to the APK and did some digging there. I had it de-compiled already and so I simply search for the domain name which both discovered systems share - northpolewonderland.com. This as well gave me the addresses of the missing hosts - it also had one advantage it gave me the corresponding names in respect to the questions, and the corresponding request's URI - something that passivetotal could not do.



So the missing three hosts are all known now;


  • dev.northpolewonderland.com (35.184.63.245)
  • dungeon.northpolewonderland.com (35.184.47.139)
  • ex.northpolewonderland.com (104.154.196.33)
Also the are all in scope




The Dungeon Game

For every host I found on the way I ran a full range port scan. This host was the first where this paid of.

Nmap scan report for dungeon.northpolewonderland.com (35.184.47.139)
Not shown: 65527 closed ports

PORT      STATE    SERVICE     VERSION

22/tcp    open     ssh         OpenSSH 6.7p1 Debian 5+deb8u3 (protocol 2.0)
|_ssh-hostkey: ERROR: Script execution failed (use -d to debug)
80/tcp    open     http        nginx 1.6.2
|_http-methods: No Allow or Public header in OPTIONS response (status code 405)
|_http-title: About Dungeon
11111/tcp open     vce?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port11111-TCP:V=6.40%I=7%D=1/5%Time=586EB5E0%P=i686-pc-windows-windows%
SF:r(NULL,AC,"Welcome\x20to\x20Dungeon\.\t\t\tThis\x20version\x20created\x
SF:2011-MAR-78\.\nYou\x20are\x20in\x20an\x20open\x20field\x20west\x20of\x2
SF:0a\x20big\x20white\x20house\x20with\x20a\x20boarded\nfront\x20door\.\nT

It seems that there is a Dungeon game running on port 11111. This was easily verified by connecting to the port via netcat or putty. While working on the first part of the Holiday Hack Challenge one of the Elf Pepper Mintstix tells you that he is playing a game of Dungeon since 1978 and he will offer a version of dungeon to play offline.

As the game online seems to be the one from 1978 I guessed they are the same. So I fired the game up and played for a while - which was not only very old school but also very useless - in respect to the challenge at hand.

~/dungeon$ ./dungeon 
chroot: No such file or directory
Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.

Running strings on the the dungeon binary file and on dtextc.dat did not help much either. All I learned was that there is a lot of text in these files :)

So I decided to run the game again, however this time monitoring what is happening with ltrace. The possible commands are displayed if one starts the game so after the game displays the initial text (which produces pages over pages if traced with ltrace) I simply entered UP as a command when ltrace stops at fgets(

putchar(10, 196, 74, 0xfbad2a84There is a small wrapped mailbox here.
)                                      = 10
putchar(62, 1, 0xe420, 1)                                             = 62
fflush(0x7f6d32f89620>)                                                = 0
fgets(UP
"UP\n", 78, 0x7f6d32f888e0)                                     = 0x625a84
__ctype_b_loc()                                                       = 0x7f6d333c36b0
__ctype_b_loc()                                                       = 0x7f6d333c36b0
strcmp("UP", "GDT")                                                   = 14
rand(6, 0, 9216, 0)                                                   = 0x6b8b4567
fseek(0x15942e0, 0xc2ff, 0, 0xc2ff)                                   = 0
_IO_getc(0x15942e0)                                                   = '\225'
putchar(89, 149, 84, 0x1599dd0)                                       = 89
_IO_getc(0x15942e0)                                                   = '\227'
putchar(111, 151, 97, 0xfbad2a84)                                     = 111
_IO_getc(0x15942e0)                                                   = '\226'
putchar(117, 150, 121, 0xfbad2a84)                                    = 117

_IO_getc(0x15942e0)                                                   = '\327'

Shortly after I entered the command ltrace shows the strcmp(s,s) function, comparing my command with the string GDT. I was pretty sure I did not see the GDT command before, but I double checked that by running the game again and read through the help. No mention of GDT.

However, if one enteres GDT nonetheless, some sort of cheat menu would display.

dungeon$ ./dungeon 
chroot: No such file or directory
Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.
>GDT
GDT>help
Valid commands are:
AA- Alter ADVS          DR- Display ROOMS
AC- Alter CEVENT        DS- Display state
AF- Alter FINDEX        DT- Display text
AH- Alter HERE          DV- Display VILLS
AN- Alter switches      DX- Display EXITS
AO- Alter OBJCTS        DZ- Display PUZZLE
AR- Alter ROOMS         D2- Display ROOM2
AV- Alter VILLS         EX- Exit
AX- Alter EXITS         HE- Type this message
AZ- Alter PUZZLE        NC- No cyclops
DA- Display ADVS        ND- No deaths
DC- Display CEVENT      NR- No robber
DF- Display FINDEX      NT- No troll
DH- Display HACKS       PD- Program detail
DL- Display lengths     RC- Restore cyclops
DM- Display RTEXT       RD- Restore deaths
DN- Display switches    RR- Restore robber
DO- Display OBJCTS      RT- Restore troll
DP- Display parser      TK- Take
GDT>

Those are a lot of commands and I played arround with them for quite some while. However most proofed not very helpful - especially as I'm not very experienced with the game. I did try to read up on some wisdom here and there - however that did not help me much.

So I tried to get into the Challenge creators heads and guessed that this is some sort of CTF where the flag (i.e., the mp3) is most likely hidden as some text somewhere.
The DT (Display Text) command was displaying text based on an entry defined by the user. So I figured that would be a feasible way to go. 
One additionaly assumption was leading my doing - which in retrospect was probably a stupid assumption - therefore beeing successful with my approach was pure luck.

I assumed for what ever reason - that the game somehow "chronologically" uses it's text from start to victory (of there is such a thing as victory). Therefore I assumed the creators might have hidden the hint to the mp3 at the end of the text.
I tried displaying text using strings before - and did not find any signs of the mp3. So I must assume the game is somehow decoding text from somewhere.

As I did not know how many lines of text the game holds I tried something big - 9999

chroot: No such file or directory
Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.
>GDT
GDT>DT
Entry:    9999
Segmentation fault (core dumped)

So its most likely not that number :) - 5000 next


chroot: No such file or directory

Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.
>GDT
GDT>DT
Entry:    5000

Segmentation fault (core dumped)

I went on with this in a binary search type of approach and managed to reach the area where there is still text and the program would not crash. 

chroot: No such file or directory
Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.
>GDT
GDT>DT
Entry:    1250
GDT>DT
Entry:    750
The pole cannot be raised further.
GDT>DT
Entry:    900
The blow lands, making a shallow gash in the #'s arm.
GDT>DT
Entry:    1100
GDT>DT
Entry:    1000
The thief bows formally, raises his stilletto, and with a wry grin
ends the battle and your life.
GDT>DT
Entry:    1050
GDT>DT 1025
Entry:    DT
GDT>1112
?
GDT>DT
Entry:    1112
??????????????????????????????????????????????????????????????????X\????????????????? ? s?D?
?+?@?g?}?l??????????????????????T??.?#? ?e?2????%?/?=?????????????Z?a?y?D?$? ? ? ????????????v?\?30? ? ? ?$
$4(                         < ! ?
   ,,^ i4M=]=S B+D;? ? ?$?-?-? ?;?+?
                                    ?q?T?]?]?kTDHTdsnnuK!B
                                                          B { T D#c+^?{?r?r?J|eeuERWOXjyc_cSZ$u8e&B.???????????? ? ?9? ?*?4?2?[?G?d?r?F???????????????????????????\?x?Y?K?u??? ? ?
GDT>
?
GDT>DT
Entry:    1112
??????????????????????????????????????????????????????????????????X\????????????????? ? s?D?
?+?@?g?}?l??????????????????????T??.?#? ?e?2????%?/?=?????????????Z?a?y?D?$? ? ? ????????????v?\?30? ? ? ?$
$4(                         < ! ?
   ,,^ i4M=]=S B+D;? ? ?$?-?-? ?;?+?
                                    ?q?T?]?]?kTDHTdsnnuK!B
                                                          B { T D#c+^?{?r?r?J|eeuERWOXjyc_cSZ$u8e&B.???????????? ? ?9? ?*?4?2?[?G?d?r?F???????????????????????????\?x?Y?K?u??? ? ?
GDT>DT
Entry:    1111
GDT>DT
Entry:    1020
The thief, noticing you beginning to stir, reluctantly finishes you off.
GDT>DT
Entry:    1030
GDT>DT 1025
Entry:    1025
"That wasn't quite what I had in mind", he says, tossing
the # into the fire, where it vanishes.
GDT>Dt
Entry:    1026
The elf appears increasingly impatient.
GDT>DT
Entry:    1027
The elf says - you have conquered this challenge - the game will now end.
GDT>DT
Entry:    1030

So the offline version of the game ends with entry 1027. The online version would disconnect if one enters numbers out of bounds. As the offline version of the game ended at entry 1027 - this is where I started with the online version too.

nc dungeon.northpolewonderland.com 11111
Welcome to Dungeon. This version created 11-MAR-78.
You are in an open field west of a big white house with a boarded
front door.
There is a small wrapped mailbox here.
>GDT
GDT>DT
Entry:    1027
The elf says - you have conquered this challenge - the game will now end.
GDT>DT
Entry:    1028
GDT>DT
Entry:    1026
The elf appears increasingly impatient.
GDT>DT
Entry:    1025
"That wasn't quite what I had in mind", he says, tossing
the # into the fire, where it vanishes.
GDT>DT
Entry:    1024
The elf, satisified with the trade says - 
send email to "peppermint@northpolewonderland.com" for that which you seek.
GDT>DT
Entry:    1023
The elf, willing to bargain, says "What's in it for me?"

GDT>

As there is no hint or clue for the challenge I started to increase the entry number further, but 1028 already was empty, therefore I started to work my way back, decreasing the entry number one by one until with entry number 1024 I hit oil.

So who would question an elf ? I wrote the guy an email and promplty received my answer - including the precious mp3.

The Uncaught Exception Handler Server

The target host ex.northolewonderland.com was identified before. Along with an URI http://ex.northpolewonderland.com/exception.php. If one visits this URI with a browser, the host complains that it requires a POST request.

Fair enough, so a POST request it will get. I used Insomnia to edit and issue my requests. The host is very helpful in getting the right format of the messages. It will tell you basically step by step what is missing - if it is missing.





It seems there are at least two operations that are supported. In order to find out how the request has to look like I again turned my attention to the de-compiled SantaGram_v4.2.apk. There one of the two operations - WriteCrashDump for that matter - can be found.


So there are a lot of fields that can be set, which would mean we have to figure out, or guess a lot of values. The most important part however is that the JSON needs to look something like this:

{
"operation": "WriteCrashDump",
"data": {
}
}

So this is exactly what I tried, and it worked somehow. The server responded with the following message:


The file is accessible, but empty. Next I tried adding one of the fields, message in that case and greeted the evels. This time the resulting file contained my message.


I tried to write various fields with various contents, php code and the like - unfortunately to no avail. I then recalled the Meteor host, where it was possible to read things that one should not read - maybe that would be the case here as well. In order to read data however, I first needed to figure out the proper strucutre of the ReadCrashDump operation. I started simple and worked my way on - with the help of the server's error messages.






So this was great, I can read crashdumps from the server. So I started to my search by brute-forcing the seond part after the dash as my experiments showed that this was the part that changed for every successful chrashdump write. For a crashdump which does not exist the server will respond with response code 500 - internal server error.


Additionally I figured that one could traverse the path of the web server - at least I assumed that from the following experiment.

From the WriteCrashDump operation we know that the files are stored in the directory doc/, this is also where they are accessible.
Reading them again either generates the 500 response code or the file is displayed.

The following will result in 500,

 {
"operation": "ReadCrashDump",
"data": {
"crashdump": "../crashdump-aegtiU"
}
}

whereas we will be able to read the file like this.

 {
"operation": "ReadCrashDump",
"data": {
"crashdump": "../docs/crashdump-aegtiU"
}
}

So I tried to read ../index and ../exception (neglecting the .php as the server would complain otherwise)

Unfortunately this did not yield anything useful - so I was back at nothing. Next I went through my notes again and checked if the elves mentioned something useful - turns out they did mention something PHP related.


After reading the blog post, and once again beeing reminded of php's great filters I decided this help me.




After some trial and error with the correct combination of convert and encoding filters it finally worked while I tried the resource that I knew existed, and well I got some base64 encoded string.


Next up was the exception.php file, which I also knew existed, just the proper path was unknown, but I simply guessed. However, simply stating the ressource itself without ../ works too.

I then converted the whole (very large) base64 string and received the plaint source code of exception.php. The first comment told me where to get the mp3 file I was after.

<?php 

# Audio file from Discombobulator in webroot: discombobulated-audio-6-XyzE3N9YqKNH.mp3

# Code from http://thisinterestsme.com/receiving-json-post-data-via-php/
# Make sure that it is a POST request.
if(strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0){
    die("Request method must be POST\n");
}
 
# Make sure that the content type of the POST request has been set to application/json
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
if(strcasecmp($contentType, 'application/json') != 0){
    die("Content type must be: application/json\n");
}
# Grab the raw POST. Necessary for JSON in particular.
$quote = "'";
$blank = "";

[...]

The Mobile Analytics Server (post authentication)

This is going to be the second host where my always port scan everything policy saved me a lot of time. This time for real. I still did some digging into the REST Interface while waiting for the port scan to finish, but afterwards I went straight after my target.

As one of the elves mentioned that -sC is a great option to use, I included it for all hosts. 


For the mobile analytics server this paid of, nmap found a git file.

Nmap scan report for analytics.northpolewonderland.com (104.198.252.157)
Host is up (0.14s latency).
Not shown: 998 filtered ports
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 6.7p1 Debian 5+deb8u3 (protocol 2.0)
| ssh-hostkey: 
|   1024 5d:5c:37:9c:67:c2:40:94:b0:0c:80:63:d4:ea:80:ae (DSA)
|   2048 f2:25:e1:9f:ff:fd:e3:6e:94:c6:76:fb:71:01:e3:eb (RSA)
|_  256 4c:04:e4:25:7f:a1:0b:8c:12:3c:58:32:0f:dc:51:bd (ECDSA)
443/tcp open  ssl/http nginx 1.6.2
| http-git: 
|   104.198.252.157:443/.git/
|     Git repository found!
|     Repository description: Unnamed repository; edit this file 'description' to name the...
|_    Last commit message: Finishing touches (style, css, etc) 
|_http-server-header: nginx/1.6.2
| http-title: Sprusage Usage Reporter!
|_Requested resource was login.php
| ssl-cert: Subject: commonName=analytics.northpolewonderland.com
| Not valid before: 2016-12-07T17:35:00
|_Not valid after:  2017-03-07T17:35:00
|_ssl-date: TLS randomness does not represent time
| tls-nextprotoneg: 
|_  http/1.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I downloaded it straight away and opened it in my local git client. I manually walked through the history and found some interesting pieces of information.

First of all I found that the database is used to store mp3 files.

-DROP TABLE IF EXISTS `audio`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `audio` (
-  `id` varchar(36) NOT NULL,
-  `username` varchar(32) NOT NULL,
-  `filename` varchar(32) NOT NULL,
-  `mp3` MEDIUMBLOB NOT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-/*!40101 SET character_set_client = @saved_cs_client */;
-

And only the guest user can download mp3 files through the webpage


Second of all while walking through the history of the git repository I found two username/password combinations that have been used in the past.




administrator - KeepWatchingTheSkies
guest - busyllama67

And last but not least I also found that the sprusage user has SELECT permissions on the users and audio table. Which will help us a great deal, but more on that later.

DB PERMISSIONS
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-
--- Dump completed on 2016-11-21 20:57:13
-
-GRANT SELECT, INSERT, UPDATE ON `sprusage`.`reports` TO 'sprusage'@'localhost';
-GRANT SELECT, INSERT, UPDATE ON `sprusage`.`app_launch_reports` TO 'sprusage'@'localhost';
-GRANT SELECT, INSERT, UPDATE ON `sprusage`.`app_usage_reports` TO 'sprusage'@'localhost;
-GRANT SELECT ON `sprusage`.`users` TO 'sprusage'@'localhost';
-GRANT SELECT ON `sprusage`.`audio` TO 'sprusage'@'localhost';
-

Turns out the administrator account still works, while the password for the guest account does not work anymore - which I knew already as I'm using the same account with a different password. However, the administrator does not see the MP3 menu item, and is not allowed to access it if pointed to it manually.

In comparison to the guest user, the administrator has the Edit menu item available. So I checked that out.

It seems the edit functionaly allows the administrator to edit a report after it was created. To test that out I needed a valid ID, which I created by generating a report by using the query function and storing the report.

Note: The report's ID will change in the course of this write-up as I abandoned the challenge for a short period of time and garbage collection seems to to its work :)
I used 5375ebcf-1bbb-4d22-9e75-cb41d51c8062 initially and 7e0bf1d4-7e03-4f78-9143-ec160897769a later on.

With the report ID available I tried the edit function

Everything looks good so far, interestingly the systems displays a query field which is the only one not submitted via the GET request.
I wondered what would happen if I add that to the query string. 



Nothing breaks, so that query string seems to be OK, next up a pentesters first urge - dump all users: SELECT * from USERS (which exists as we know from git).



This also looks fine. Now the report should be updated and contain some precious data.


What the ... I know I have access rights to that database - or do I ? It was the history file after all, maybe there are changes afterwards....

.. well or I'm simply stupid: Case matters! .. and the table is called users (all lower case!). After fixing that minor flaw I successfully proofed that I can run my own queries and the results are displayed in the report that is edited (or updated to be precise). 
As the hunt is all about mp3 - so audio - files, I turned my attention to the audio table.


Well this worked quite well, so not only guest does have a mp3 file assigned but so does the administrator. However accessing the file through getaudio.php does not work - and the guest user can only download its own file.

In the report above one can see that all strings are displayed correctly while the mp3 blob itself is empty. The usual way to extract blobs would be to SELECT into OUTFILE, but this was no option here. 
I needed a way to somehow convert the blob into something that is printable in the browser. Therefore I did some research and found the CONVERT() function which I applied to the mp3 field.

https://analytics.northpolewonderland.com/edit.php?id=7e0bf1d4-7e03-4f78-9143-ec160897769a&name=test&description=test&query=SELECT%20CONVERT(mp3%20USING%20utf8)%20FROM%20audio

So this seems to work, however it only worked for the ID3 Tag data included in the mp3, but it shows that I can do things to the data blob. 
From the challenges above and also from various pentests I know that base64 encoding is useful in every situation, especially if one wants to transfer files through text channels. 
But I was not aware of any base64 encoding technique in MySQL.
Luckily the internet is my friend and proofed to be a valuable one once more - searching through mysql's documentation with "base64" found the keys to the castle.

After applying the function to the mp3 field my browser presented  the base64 encoded mediablob.

https://analytics.northpolewonderland.com/edit.php?id=7e0bf1d4-7e03-4f78-9143-ec160897769a&name=test&description=test&query=SELECT%20TO_BASE64(mp3)%20FROM%20audio



However in order to figure out which mp3 I was looking at I needed to add the username to the query once again.

https://analytics.northpolewonderland.com/edit.php?id=7e0bf1d4-7e03-4f78-9143-ec160897769a&name=test&description=test&query=SELECT%20username,%20%20TO_BASE64(mp3)%20FROM%20audio

Now I had the right file and all that was left to do was to convert it back into its original - not encoded - format.

root@dergeraet:~$ base64 -d analyticsmp3_base.txt 
ID3 TRCK 7TIT2 7���dbase64: invalid input
root@dergeraet:~$ base64 -d -i analyticsmp3_base.txt > analyticsmp3.mp3
root@dergeraet:~$ file analyticsmp3.mp3 
analyticsmp3.mp3: Audio file with ID3 version 2.3.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, JntStereo
root@dergeraet:~$ md5sum analyticsmp3.mp3 
313e7e370fd7d5232bb569f21856d9f4  analyticsmp3.mp3
root@dergeraet:~$ mv analyticsmp3.mp3 discombobulatedaudio7.mp3

The Debug Server 

I'm not sure why, but I did this server as the last one. It shares some similar approaches than the rest of the servers, so it was quite easy to solve it. The host was identified before dev.northpolewonderland.com (35.184.63.245) and is in scope of the challenge. As it has proven very useful I once more started with the SantaGram_v4.2.apk. I simply searched for the hostname and then chained the searches together to find the correct file where the function using the host resides in.


So the functionally that corresponds to this host can be found in EditProfile. One last time I fired up jadx to check out what the function is doing.



The function is building another JSON object which is then sent to the host. Once more I used Insomnia to issue my requests. I started of with a blank request and received nothing but the status 200.
So the question is what is missing, after looking at the code it became clear that the data in the fields can be easily generated. For the date I would simply generate a new timestamp, the UUID can be extracted from my virtual device, or I can use the standard one, for freemem I can basically put any number but the debug field is based on the apk itself. I quickly checked what the two functions getCananonicalName() and getSimpleName() would return based on how they are called.

I figured com.northpolewonderland.santagram.EditProfile, EditProfile would be the correct string as assembled in the apk.

So I gave it a first shot only considering the debug field, all others I left blank.


And it worked. I got some data back, basically the server is reflecting what I submitted. All but one, there is one new field called verbose.

I checked the text file mentioned in the response, which contains nothing but what I submitted. 

The verbose field is set to false, what if I set it to true ?


Well the response becomes more verbose ... and once more mentions another mp3 file - debug-20161224235959-0.mp3. 

Hooray I've got them all!


Part 5: Discombobulated Audio


However my work is not yet done, I have seven audio files now which needs to be re-assembled and then there needs to be something done with the playback speed, as the sound veeeeery sloooo0000oooooow.

I simply added them to a VLC playlist in order and increased playback speed, the problem is, that the steps VLC offers are not granular enough. All I could hear was "christmas". 
So as the next step I used WavePad to reassemble the seven files into one - mainly because changing the playback speed was easier if only dealing with one file.


I've played arround with the Effects -> Speed Change quite a bit but never could I understand the whole sentence. At roughly 215% speed adjustment I understood: "Father christmas santa clause or as him jeff" - to be honest I was clueless. And without the help of my old friend the internet and its search engines I would most likely still be clueless.



So the full quote from the audio file is "Father Christmas, Santa Claus or, as I've always know him, Jeff" 

 It was easy enough to test the truth of that, so I entered the north pole once more and visited Santa's office where I tested the quote as the password to the door in the corridor behind his bookshelf. And guess who I've met there....


Dr. Who ... he abducted Santa or Jeff, to use his North Pole Wonderland Magick to prevent the Star Wars special from being released (Question 9 and 10).




That being said, here are the achievements I earned in the North Pole game along with my inventory quests (I missed to pick up the quests in the dosis house) and a small but which prevented me from picking up a NetWars coin.













With the last two questions answered I conclude my write-up of the 2016 SANS Holiday Hack Challenge, it was a good time participating and I'm looking forward to next years challenge. Once again my thanks and kudos to the team behind this years challenge. Great job!


Links: 


No comments:

Post a Comment