Introduction
BountyHunter is a fun Linux box on HackTheBox that has XXE injection on a PHP form, which exposes DB credentials. This DB credential is reused as a password for a user on the box.
The box also has an internal python3 script which could be run as elevated privileges.
This script uses eval
by which we get command injection, which leads to superuser access to this box.
Scanning & Enumeration
Massscan
sudo masscan -p1-65535,U:1-65535 --rate=500 -e tun0 10.10.11.100
Discovered open port 80/tcp on 10.10.11.100
Discovered open port 22/tcp on 10.10.11.100
NMAP
sudo nmap -sC -sV -oN 10.10.11.100.nmap 10.10.11.100
# Nmap 7.80 scan initiated Sat Jul 31 13:19:13 2021 as: nmap -sC -sV -oN 10.10.11.100.nmap 10.10.11.100
Nmap scan report for 10.10.11.100
Host is up (0.14s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jul 31 13:19:42 2021 -- 1 IP address (1 host up) scanned in 29.04 seconds
So the open ports we have here are:
80
and22
. Port 80 is runningApache server 2.4.41
.
Foothold
We add the box’s IP to the hosts file at /etc/hosts
so that we can use http://bountyhunter.htb
.
10.10.11.100 bountyhunter.htb
We can test and see that port 80
is using PHP
.
Running DIRB
dirb http://10.10.11.100 -X .php
-----------------
DIRB v2.22
By The Dark Raver
-----------------
URL_BASE: http://bountyhunter.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
EXTENSIONS_LIST: (.php) | (.php) [NUM = 1]
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://bountyhunter.htb/ ----
+ http://bountyhunter.htb/db.php (CODE:200|SIZE:0)
+ http://bountyhunter.htb/index.php (CODE:200|SIZE:25169)
+ http://bountyhunter.htb/portal.php (CODE:200|SIZE:125)
-----------------
DOWNLOADED: 4612 - FOUND: 3
We find a portal here http://bountyhunter.htb/portal.php
which says “Portal under development. Go here to test the bounty tracker.” and links to http://bountyhunter.htb/log_submit.php
.
On this page, we have a form that sends data back to the server.
XXE injection bug
We use Burp Suite to look into the data being sent by using Interceptor. We find that /log_submit.php
sends a POST req to /tracker_diRbPr00f314.php
(lol, the file name is dirb proof
) with payload =>
|
|
We can decode the base64
encoded data. The XML
data being sent looks like this:
|
|
As we can guess the bug
here should be in parsing the XML input, most probably XXE (XML external entities) injection 1.
We now try to exploit this using Burp Suite’s Repeater 2.
If we use the following XML, we can read the hostname
file located at /etc/hostname
Here, we have added an extra line, as highlighted.
|
|
We can see that we read the file /etc/hostname
which has the text bountyhunter
in it.
Similarly, we can get /etc/passwd
’s contents.
|
|
The following is the output:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
sshd:x:111:65534::/run/sshd:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
development:x:1000:1000:Development:/home/development:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
usbmux:x:112:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
Of these only development
and root
are the users having their shell as /bin/bash
and HOME directory set, meaning they are non-system users or real users.
We already know that on submitting the form on log_submit.php
we get If DB were ready..
text and also we have found a db.php
with the DIRB scan!
Obtaining DB credentials
Now we read the /db.php
file in a similar manner:
|
|
⛔ But, we get nothing!! This happens because after the contents of /db.php
is added into XML,
the data is then stripped out while returning by /tracker_diRbPr00f314.php
.
Hence, we need to encode the PHP strings into something else so that we could prevent this from happening and get back the contents of /db.php
.
We do this by using php://filter/convert.base64-encode/resource=<filename>
3
This is the XML data we can use to fetch the db.php
file:
|
|
We can now send this via the BURP repeater.
And we get the file contents of DB having the below content.
|
|
Obtaining user.txt
We try logging into user development
as we saw in /etc/passwd
file using SSH
and password as it was mentioned in /db.php
ssh development@bountyhunter.htb
We get user development
’s shell 🐚!! And also user.txt
flag
Privilege Escalation
We see contract.txt
file in /home/development/
which reads:
This means that there should be a tool
/scripts
/binary
which could have sudoers
permissions! 😈
sudo -l
reveals user’s privileges for a special script
Running sudo -l
reflects this:
We have a file /opt/skytrain_inc/ticketValidator.py
which can be run using python3
as a superuser
(root
in this case) without supplying any password.
Below are the contents of /opt/skytrain_inc/ticketValidator.py
:
|
|
Exploiting eval
to get command injection
What ticketValidator.py
does is, it gets a file path in input and processes it, and returns whether the ticket is Valid
or Invalid
.
Notice line-no 34 which is using eval
4 to evaluate the expression in the ticket. For ex. 704+1
will return 705
.
Using the logic in code and parsing we have the following ticket Valid
.
|
|
We can use the eval
function in python3 to execute a system command and this command will get executed as root
!
Accordingly, ticket.md
can be crafted as shown below to get a reverse shell.
|
|
Obtaining superuser access & root.txt
We make a new file ticket.md
with the above contents and then run the below command on target box:
sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
We listen on attacker box with:
nc -lvnp 4242
Then enter the file path for ticket.md
.
For me it was /tmp/ticket.md
development@bountyhunter:/tmp$ sudo /usr/bin/python3.8 /opt/skytrain_inc/ticketValidator.py
Please enter the path to the ticket file.
/tmp/ticket.md
A reverse shell is sent back to our listener.
And we get root
’s shell!! Yayy 🎉