Hack in the Box 2016 – MISC400 Writeup (Part 1)

The challenge

This year the CTF prize sponsors Beyond Security contributed a 400 point challenge:

MISC400 - Above and Beyond
Even chefs need a bit of help sometimes, especially when it comes to IT related subjects.
Luckily, the guys at Beyond Security are always willing to offer a helping hand through their IT blog.
So, if you have any trouble, try the blog at

The basics

Visiting this blog presented us with the following website:

Browsing the website we identified a number of read only, static pages – nothing particularly interesting. However, by viewing the CSS source we identify the following:

So, there must be a form available somewhere, eventually one of the usual suspects gives a hit and we find the admin panel:


This admin panel requires authentication and the ‘hint’ implies brute forcing is not a good solution. Luckily, the HTML source gives our next hint, backups are stored on the server:

Accessing this directory we identify a number of backup archives are accessible:

Selecting a backup archive at random, we find it is password protected.

So, let’s try them all:

wget --mirror
for a in *.tar.gz; do tar -zxvf $a; done

With access to the source code, things start to get interesting:

Needle in the haystack

After some precursory browsing of the source code, we find the Session class to be particularly interesting. The Session class is implemented as a singleton and can be directly initialised through the admin directory, via either the index.php or manage.php URLs.


This Session class contains (among others) the following functions:

So, we have an arbitrary object injection when the Session object is initialised.

The question becomes, what can we do with this?

Tracing our flows

With these kinds of challenges (i.e. too many lines of source code), I always prefer to draw the call graphs to trace the function flows and thereby gain a clearer understanding of how the application works and which functions we can call.

To prevent unnecessary confusion from the scratchings I made during the CTF, I have reproduced these graphs with the help of Dia.

Below, we can see the function flow (as seen in the source above) to reach the vulnerable unserialise call with our user supplied data:

Now we have a clear understanding of how to reach the vulnerable function call, we can start looking for ways to abuse this object injection.

Digging deeper

Via the User class, we identify the following function:

As we can see, an SQL query is generated utilising an escaped version of the User object’s _user variable. However, prior to being inserted into the query, the data is sanitised using PHP’s real_escape_string.

As per the documentation (and assuming ‘regular’ character sets), PHP’s real_escape_string call encodes the following characters:

Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.

As per the function above, the escaped user input is not enclosed within quotes, therefore this function is still vulnerable to SQL injection attacks.

As an example, we can circumvent the real_escape_string call by creating a User object with a username of ‘1 or sleep(5)‘, which will result in the following SQL query after sanitisation (and will cause the database to sleep for 5 seconds):

SELECT last_login FROM $users_table WHERE user=1 or sleep(5)

The only problem with this path of attack is the rewind function is never called by the application..

Calling uncallable functions

Taking a closer look at the User class, we see it implements the Iterator interface. This interface allows the associated object to be used as part of a foreach loop. To facilitate this, the interface permits custom implementations of the following functions:

As per the PHP documentation, rewind is used to ‘rewind the Iterator to the first element’ and is the first method called at the start of a foreach loop.

With this understanding, the SQL injection can be triggered as follows:

  • Create a User object with a customisable username
  • Utilise this object in a foreach loop to trigger the Iterator (thereby rewinding to the first element)
  • Perform the SQL injection via the insecure real_escape_string sanitisation
  • Extract the administrator’s username and password

As we identified in the code snippet above, the loadSession function is called with our user supplied data as part of a cookie. This function takes the cookie data, base64_decodes it, unserialises it, then finally performs a foreach loop to map the data as part of an array within the object.

Using this information, we can create our own dummy function, which creates a custom serialised object matching the conditions outlined in our above attack:

Setting the $session output as our session cookie and accessing the application will cause the above attack chain to be triggered.

Automating the injection

To make life easier, we can set-up a local proxy:

Then allow sqlmap to perform the heavy lifting:

python sqlmap.py -u "" -p1 --level=5 --risk=3 --sql-shell

Once the injection point is identified, we can perform arbitrary SQL commands against the server database, such as extracting the username and password of the admin user:


Tracing our flows (again)

Now we have access to both the username and the MD5 password for the admin user of the application. Assuming this MD5 cannot be trivially cracked, we need to find another way to abuse this information.

Via the application there are two ways to attempt to access the administrative panel, either via index.php or manage.php which result in a slightly different authorisation check.

Via index.php we can access functions in the following paths:

Via manage.php we can access functions in the following paths:

Therefore, it is possible to instantiate our User object and influence the subsequent checkPassword authorisation flow with different boolean values for the _is_session parameter:

Since we already know the MD5 value of the password (via the SQL injection), we want the _is_session parameter to be set to true, thereby skipping the function. We can achieve this condition with a secondary object injection attack:

  • Create a User object with the known valid credentials
  • Access the function flow via manage.php (resulting in the MD5 function not being called)
  • Gain access to administrative functions without cracking the password

We can therefore gain administrative access to the application with the following object:

Setting this as the session cookie in our browser and accessing the administrative interface via manage.php permits us to successfully access the application as an administrator:

Back to the source

Now we are administrators, we have access to some interesting new functions:

As an attacker, the download function looks most interesting. A user supplied website can be downloaded via the file_get_contents call, then a regular expression is performed against the content to obtain the website’s title. The website data is then saved in a base64_encoded format in the files directory; all within a native system call.

The output of the website’s data is saved based on the matches array which is a result of the preg_match call:

$matches[0] will contain the text that matched the full pattern, $matches[1] will have the text that matched the first captured parenthesized subpattern, and so on.

As per the function definition and the above implementation, we can control the data stored within $matches[1], by hosting our own webpage with a custom, malicious <title> tag which we can then abuse to break out of the underlying system call.

Remote code execution

As an example, we can ‘break out’ of the system call and perform ls on the local file system via the following:

So, let’s set up a website on our local machine with these malicious <title> tags:

Then download this page via the management application:


Finally, we have obtained code execution on the application server.

An obvious flag was not accessible in the webroot, so the next step is to gain a shell on the server (they removed python for some reason?):

Surely we must have earned some points by now right?


ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=85ac919bb9c5311f8bdbcf2e6255814d227d8b76, not stripped

Stay tuned for part 2…

Synology NAS DSM 5.2 Remote Code Execution (RCE)



RCE in Synology NAS DSM 5.2 due to lack of input sanitisation. RCE triggered indirectly via port forwarding mechanism in the NAS UI.

Getting started

I recently bought a Synology DS416 NAS and noticed during the set-up process you are first required to download the device firmware, which is then flashed to the device via the setup web interface.

Interested in my new devices security, I decided to take a look at the firmware while the system was installing.

Firstly, let’s download the DSM 5.2 firmware (unsure which versions are affected by this vulnerability) from the official Synology download center and identify what we are dealing with:


So, the archived DSM_DS416_5644.pat file contains a number of subsidiary files and packages, as well as what looks like a compressed kernel. As the device has no default storage (OS is installed to your separate HDD’s), hda1.tgz immediately looks interesting.


So hda1.tgz is another archive, in which we find what looks to be a Linux filesystem.

After some cursory browsing, I noticed some helper php files are in use, so let’s look for some low hanging fruit.


PHP 101

Let’s take a look at our first grep result:
cat ./etc/portforward/routerdb/BT/HomeHub2.0/Version8.1.H.G_TypeA/dele_rule.php

As we can see, the php script above appears to contain the following functionality:

  • Take inputs passed to the script
  • Add port forwarding rules via a 3rd party routers web interface
  • Delete port forwarding rules via a 3rd party routers web interface

Interestingly, when a port is deleted the (unsanitised) inputs passed to the script are unsafetly concatenated into a string, then passed to a php system call. If we can control these inputs, we can ‘break out’ of the string and append arbitrary commands to the system call; thereby obtaining RCE on the NAS device.

A first look

The NAS OS has installed by this point, so we can login to the device and take a look around the UI. The UI looks nice and the control panel appears to have many features. One in particular that takes my immediate interest (based on the script above) is ‘External Access’.



The ‘External Access’ option permits users to configure their router and from within the NAS UI they can perform actions on their router such as adding or deleting forwarded ports. Based on the naming convention of our vulnerable script above, the ‘BT: HomeHUB2.0’ looks promising. By using the ‘custom router account’ we can also identify what appears to be the parameters being passed to the script.

Gaining access

Assuming these parameters are passed directly to the php script with no intermediate sanitisation, we can attempt to modify the php system call by ‘breaking out’ of the unsafetly concatenated string and appending our own arbitrary commands.

In particular, the offending line:

For example, by changing our router password to a\';touch /tmp/test, we should ‘break out’ of the initial command and append touch /tmp/test, which will then also be passed to the system call. Thereby writing the file test to the /tmp directory of the NAS device.

Creating files is well and good, but to make the most of an RCE, we want a revere shell.

For example, using python we can set the following password for the HomeHub2.0 router, which will initiate a reverse shell from the NAS device to our system listening at on TCP port 1234 when the affected call is triggered:

Once the backdoored router password has been added, we simply need to follow the information flow as per the script above to trigger our backdoor and gain a reverse shell:

  • Login to the NAS UI
  • Set up the HomeHub2.0 router with the backdoored password
  • Delete some router rule

Automating the process

Naturally, we want to automate this attack. Unfortunately, the login process to the NAS is not straight forward. When logging in, the username and password (and some additional parameters) are encrypted with both RSA and AES (assumedly to protect against MITM attacks on the network) and then the encrypted data is posted to the server.

Looking at the client side JavaScript files we can identify how this encryption is being performed.

During the login process, the client also submits a request to obtain the server’s public key. As seen in the script above, when a response from the server results in a failure, it’s possible to submit the valid login request in plain text. Therefore we don’t need to re-implement this encryption method, we can instead abuse the insecure fall back.

Firstly, we login to the device:

Secondly, we utilise the valid cookie and custom synology headers to set up the vulnerable router with our backdoored password:

Finally, we trigger the backdoor by removing a port forwarding rule:

Pulling it all together


It’s running as root, so that makes privilege escalation a breeze.

Note: The astute readers might notice the vulnerable php script above will only follow the aforementioned data flow when specific patterns are matched (based on the responses received from the routers web interface). Initially, I set up a faux router (based on a real web interface for HomeHub2.0 identified via a Shodan search) to give the correct dummy responses to ensure the data flow was followed as expected. However, this ultimately was not needed to trigger the RCE, so I suspect something even more sinister is going on under the hood; which I did not investigated.

PS: for those of you playing along at home who also want a shell on their NAS. I later found it’s also possible to just enable SSH via the UI 🙂

Edit: At the request of the Synology security team, and to avoid some confusion in the usage of the ‘test’ account in the POC above, this attack can only be performed with a valid administrative account. This clearly affects the likelihood of this attack, however there a few things to consider in this particular case. Firstly, this is not intended functionality by the developers. Secondly, many of these devices are placed on the Internet and only accessible via 1 port (their web interface); so being able to gain a root shell via this method and bypass corporate firewalls/routers/etc is certainly interesting.

Disclosure timeline

13th December 2015 First contact requested information on submitting security vulnerabilities
14th December 2015 Given address of PGP key and security contact email address
14th December 2015 Encrypted information about vulnerability including POST requests for a POC
16th December 2015 Similarly, given address of PGP key and security contact address (from another support address)
16th December 2015 Informed both support addresses that I have received the PGP key and submitted a POC. Requested information on when to expect a response
17th December 2015 Received response that the information was received and had been sent to the appropriate teams for investigation
23rd December 2015 Emailed to request status of the issue
24th December 2015 Received response that the issue is valid and fix will be applied to next DSM release
24th December 2015 Emailed to request an ETA for when the new DSM version will be published
24th December 2015 No schedule for release. Current estimate is ‘some time in February’. Will be notified when the fix is released.
22nd February 2016 Requested whether the fix was shadow-patched in the 5.2-5644 patch released on the 19/2/2016
22nd February 2016 Security team responded that the issue was fixed on January 22nd in version: 5.2-5644 Update 3 under the confusing nomenclature ‘Enhanced network stability when port forwarding is configured.’
22nd February 2016 Blog post published

How to add an XSS-able bot to your CTF

During CTF events it can be interesting to provide XSS challenges for players to solve. This post will discuss automating the process of executing user supplied JavaScript – aka running XSS-able bots within a CTF environment.

PhantomJS is a headless WebKit useful for automating tasks such as functional or display testing. Another use we can adapt PhantomJS for is to visit web pages known to contain user supplied JavaScript and executing these payloads.

Once installed, PhantomJS can be run with user supplied JavaScript.

The example script below will visit a known vulnerable url where CTF players are tasked with exploiting and storing their XSS payload.

The onResourceTimeout and open functions handle pages where user payloads hang and initial access of the url respectively.

You will also see the setTimeout function surrounding phantom.exit(). We found during CTFs a timeout was required to ensure all types of XSS payloads (such as complex payloads containing multiple redirects) were executed by PhantomJS – this value may require tweaking for individual circumstances.

Once the above code has been adapted as required, we can call PhantomJS to XSS itself continuously.

Where the command line options permit the following:

  • ignore-ssl-errors: ignores SSL errors, such as expired or self-signed certificate errors;
  • local-to-remote-url-access: allows local content to access remote URL;
  • web-security: enables web security and forbids cross-domain XHR;
  • ssl-protocol: sets the SSL protocol for secure connections.

As an example, once our XSS bot is executing – PhantomJS should show similar output to the following:

For testing purposes, we can inject the following JavaScript into the vulnerable url PhantomJS is polling:

Setting up some listener on the required port:

Once our PhantomJS XSS bot accesses the vulnerable url and executes our payload, we receive a callback to our listener:

Hack in the box teaser 2015 : Forensics 1000

In preparation for the Amsterdam Hack in the box CTF this year I took a look at the Forensics 1000 challenge, the description of which you can find below.

While doing forensics on the HEAVENWEB's server we found a possible ACTOR.
We scanned the interweb for possible traces left by this ACTOR and found an opendir containing HEAVENWEB_SCRAPE.tar.xz [sha256: 6188c47846d306f29315c5df85c507052d20e98e592e08bdf1b35b46c7f84564].
We believe they use a proprietary crypto application only known to this ACTOR.
Are you able to find the flag?
HINT: https://www.youtube.com/watch?v=zuxlLLeKZZ8

The HEAVENWEB_SCRAPE.tar.xz archive contained 2 files:

  • HITB_FOR1000_2015: data
  • HITB2015_FOR1000.dmp: ELF 64-bit LSB core file x86-64, version 1 (SYSV)

Running strings on the HITB2015_FOR1000.dmp file, we see it is an operating system memory dump:

  • /boot/vmlinuz-

Some cursory googling, coupled with the challenge name we identify the operating system as North Korea’s RedStar. Inspecting the HITB_FOR1000_2015 file we find references to a file system as well as some common encryption buzz words.


After this quick analysis, we watched the hint video and at around the 12.00 minute mark we see a demonstration of Red Star’s custom encryption application – Bokem.

The video further explains Bokem is native to Red Star and requires root privileges to run.

So, let’s install Red Star and escalate to root:

Let’s fix networking while we are at it:

After a quick sudo –s you should be able to execute Bokem with root privileges.

Next we can create our own Bokem container, after which we identified that the challenge is also a Bokem container which we need to access.

After creating our own container, we notice the .bokem3.conf file in our current directory, which contained:

To this configuration file, we can append the container from the challenge to attempt to load it:


Unsurprisingly, the challenge container 93a0c2f4 requires a password.

Given this is a forensics challenge, let’s assume we can find what we need in the challenge. So, let’s mount our own container and dump our machine memory. Assuming you are using a virtual machine, you can do this by simply taking the .vmem file of a snapshot.

So now we have the following:

  • Our container file, to which we know the password;
  • Our memory dump, including a running and decrypted container;
  • The challenge container file, which we want to decrypt and do not know the password;
  • The challenge memory dump, hopefully including a running and decrypted container.

Let’s start by analysing our own container.

Looking at our own container with the name and password of test we notice in the header:

Which is the md5 of our password, followed by our container name.

Similarly, in the challenge container we notice in the header:

Which is the md5 of the container password (which we couldn’t crack), followed by the container name.

So we need some more information from the challenge container, let’s take another look at our running container on Red Star.

Dmsetup is a low level logical volume management tool. Dmsetup can be used to create and remove devices, get information about devices or reload tables. Using the dmsetup tool we can gain some information about the currently mapped devices on the system. Luckily, dmsteup also supports displaying of the encryption keys used.

Let’s take a look at our mapped container and its associated encryption key:

So, our encryption key is as follows:

If we lazily search for our key in our memory dump we identify an interesting instance:


The memory structure identified contains the md5 of our password, as well as our known encryption key some bytes above.

Doing a similar search using the password hash from the challenge, we identify a similar structure in the challenge memory:


Based on our testing container, be6b50300e87ea15da0884d5e44781ffbf8000286db03dade00ce4b64cad0bf4 appears to be the encryption key used by the challenge container.

So, let’s try and mount the challenge container using the above identified key.

We can create a device and specify a mapping table using dmsetup, for this we need the following table parameters:

We can identify most of this information from the mapping settings in our similarly sized container, except the sector offset.

Looking at the challenge container randomness with a hex editor we can identify that the file’s encryption offset appears to start at 0x200 or 512 bytes into the file. For dmsetup a sector is always defined as 512 bytes, so we can identify our new table as follows:

Now we can mount the challenge container:

Once mounted, we identify a single file in the container flag_HITB.txt which contained:

The hash that never was

It’s a familiar situation, you’ve found some vulnerability and popped a limited shell.

You’ve enumerated services, the kernel, applications, plugins, the distribution, jobs, configs, file permissions, etc, etc – but you can’t find a feasible way to escalate your privileges.

I present the following scenario.

There is a web app on the system and you suspect the system root user (who also uses the web app) suffers from the common (and tempting) affliction of password re-use.

You’ve gained access to the database and dumped the web app root user’s password – but can’t crack it.

So, what can we do?

Intercept the password before it’s hashed.

For this demo we will be using a default WordPress install.

Our first step is to find where authentication is handled:

So, we are looking for loginform from assumedly wp-login.php (this is not always so trivial).


Once we have identified the location of the authentication form, we want to hijack the flow of execution and intercept the password – before it is hashed and compared in the database.

We can achieve this using file_get_contents and raw post data.

The file_get_contents function can be used to include some resource from an arbitrary domain, while php://input allows us to read raw POST data directly from the request body.

By combining these components we can send authentication POST data to some arbitrary site prior to being hashed (note: this code should be placed in the execution flow where authentication is handled):

Next time some user logs in, we will receive the following plain text in our server logs:

The friendly phisherman

While technical resilience to security can be quantitatively tested and evaluated at some point in time. The human factor is often a weak point which is difficult to assess, even more difficult to rely upon (consistently) and can result in compromise even where technical issues have been addressed.

A simple way to test organisational resilience or the effectiveness of staff security awareness training is to perform social engineering exercises. While areas such as physical access, cold drops and phone calls all fall under this remit (among others), this post will focus on a technique with a very low barrier of entry and expertise – phishing.

So, how can we test an organisations resilience to a phishing campaign?

Launch one.

Our friendly (note step 3) phishing campaign will comprise of 3 simple steps:
1. Obtain email addresses for some company (target)
2. Send an email to each address containing a uniquely identifiable URL (phish)
3. Record which users follow the offending link (log)

To record which user has followed our phishing links, we will send URL’s with the following format:
http://yoursite.com/index.php?id={base64_encode(target email)}

Let’s start by setting up our logging script.

Using php we want to unencode the user’s email address from the $_GET['id'] parameter and log the result to a text file:

We will also add some html so as not to arouse too much suspicion:

Any user who follows our link will be served a 404 page (note a 302 would work just as well), while their details are logged in the background:


Next we need a list of target email addresses for some given domain, for our purposes we will use theharvester tool, which we will call from our python script:

To make our links appear less suspicious we will utilise the free bit.ly url shortening service, (requires account registration to obtain an api key):

Once we have our list of targets we email each user with our enticing phishing email, they will then receive a custom email in their inbox:


Each user who follows the link will then have their email address logged:


Using this method, we can easily and automatically identify users who are more likely to succumb to a real phishing attack and update staff awareness training as appropriate.

A full python code listing can be found below:

The risk chain

An important consideration when scoping a web application penetration test is to understand exactly what the application does, the data it manages, who has access and why. This allows us to prioritise and customise our testing approach to tailor for potential high risk attack vectors to our client.

This allows us to give the client some scaled rating between (as an example) 1 (low) and 5 (high) for each vulnerability identified based on the inherent risk.

What I will talk about today is a real world example where chaining seemingly low risk vulnerabilities together can result in a high risk compromise.

Pre-engagement we discovered an application handled credit card information; however we were assured the details were sent encrypted to a payment gateway via a dedicated line and not stored locally.

Seems reasonable.

During the engagement we found some common (arguably) low risk vulnerabilities.

The application was:
Vulnerable to framing / clickjacking attacks (1 / 5)


Google and Microsoft (and this site..) have a slightly different take on this vulnerability.

Vulnerable to unknown (2 hours+) session expiry timeouts (2 / 5)

Possible to enumerate valid email addresses via non generic password reset error messages (2 / 5)

Vulnerable to predictable sequential username identifiers (1 / 5) – justified with an aggressive account lockout policy.

Insecure direct object reference vulnerability – more specifically it was possible to view payment invoices of arbitrary customers by manipulating the reference variable (4 / 5).

So, what could an attacker do with this information?

Using javascript we can iterate over each sequential customer number from 1..n (where n is our test account and most recent id number) to view every payment invoice stored in the system.

Opening a few of these at random and we find a bigger problem.

If a user paid by credit card, their payment details are returned as part of the invoice in the following format:

378X 822X 310X 0X – 24X

Luckily it’s not possible to obtain valid credit card information with those X’s truncating the real value.

Great, so you found some credit card numbers what’s this have to do with that chaining?

I present the following scenario.

An attacker sets up a hidden iframe on some site embedding the vulnerable target web application (1). Exploiting the sequential username identifier (1) and direct object reference vulnerability (4) a javascript payload is prepared which downloads every potential payment invoice from the application.

Next our attacker enumerates valid registered email addresses using the non-generic password reset error messages (2) and sends out phishing emails to every identified valid user (or alternatively sets up a watering hole).

If some user who has previously logged into the application (remember how sessions don’t expire? (2)) visits the attackers site, the javascript payload will download every payment invoice stored in the system.

It is now trivial for our attacker to iterate over each invoice and parse for credit card details – without ever having to authenticate.

1 + 1 + 4 + 2 + 2 = 10