Soccer — Tiny File Manager Upload and dstat Plugin Privilege Escalation
- Tools
- rustscan, feroxbuster, netcat, curl, sqlmap, sqlmap-websocket-proxy, ssh, doas, dstat
- Skill demonstrated
- Linux web foothold and privilege escalation through upload execution, database injection, and a delegated doas rule
- Tags
At a glance
Section titled “At a glance”| Field | Value |
|---|---|
| Difficulty | Easy |
| Target environment | Ubuntu Linux; nginx 1.18.0; Tiny File Manager 2.4.3 |
| Starting position | Unauthenticated network access |
| Objective | From exposed file-management software to root through an executable upload, WebSocket SQL injection, and a delegated dstat rule |
| Outcome | Web-service shell, SSH access as a lab user, and a root context through dstat plugin loading |
Summary
Section titled “Summary”Soccer is an Easy-rated Hack The Box Linux lab that chains an exposed file manager, an executable upload directory, a WebSocket SQL injection flaw, and a delegated privilege rule into root. Default credentials open Tiny File Manager, the upload directory runs PHP, local nginx configuration reveals a second application virtual host, and its ticket-checking WebSocket is injectable and discloses an SSH credential; a doas rule then permits dstat, whose Python plugin loading yields root. Target and attacker addresses, virtual hosts, account names, credentials, and the reverse-shell payload are replaced with role-based placeholders; command syntax is preserved.
Attack path: Tiny File Manager default access → upload-directory PHP execution → web-service shell → local nginx configuration → secondary virtual host → WebSocket ticket-check SQL injection → database credential recovery → SSH as lab user → delegated doas rule for dstat → Python plugin execution → root
Context and Objective
Section titled “Context and Objective”- Target: an Ubuntu Linux host running SSH, nginx, and an unidentified service on port 9091.
- Exposed services: SSH (22), HTTP (80), and a high port (9091) later identified as the ticket-checking WebSocket.
- Starting position: unauthenticated network access, with no provided credentials.
- Objective: follow documented paths from web access to privileged execution, showing how default configuration, an executable upload, an unvalidated WebSocket endpoint, and a delegated rule combine.
- Constraints: activity was confined to the Hack The Box lab environment.
Approach and Evidence
Section titled “Approach and Evidence”1. Service and Content Discovery
Section titled “1. Service and Content Discovery”Observation: a full TCP scan exposes three services, and HTTP redirects to a hostname-based site, so virtual-host handling is required before web enumeration is useful.
rustscan -a <TARGET_IP> --ulimit 5000 -- -Pn -sC -sV -oN <SCAN_OUTPUT>feroxbuster --url http://<PRIMARY_VHOST> --wordlist <WORDLIST> -o <CONTENT_OUTPUT>Truncated scan and discovery output:
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux)80/tcp open http nginx 1.18.0 (Ubuntu)9091/tcp open xmltec-xmlmail?301 GET /tiny => /tiny/Significance: the redirect confines enumeration to the primary virtual host, and the discovered /tiny path exposes a file-management interface.
Result: SSH, nginx, and a high port are exposed, the primary virtual host is identified, and /tiny hosts an application.
2. Default-Credential Access to Tiny File Manager
Section titled “2. Default-Credential Access to Tiny File Manager”Observation: /tiny hosts Tiny File Manager 2.4.3, and public documentation and common deployments ship with well-known default credentials.
Action: authenticated to the file manager with the documented default credentials, <DEFAULT_USER> / <DEFAULT_PASSWORD>.
curl -s -c cookies.txt -X POST http://<PRIMARY_VHOST>/tiny/ -d "fm_usr=<DEFAULT_USER>&fm_pwd=<DEFAULT_PASSWORD>"The response confirmed the session:
You are logged in
Tiny File Manager 2.4.3Significance: default administrative credentials grant full file-management access, and the footer identifies the deployed version.
Result: authenticated administrative access to Tiny File Manager is obtained.
3. Executable Upload to Code Execution
Section titled “3. Executable Upload to Code Execution”Observation: the /tiny/uploads directory executes uploaded PHP files; a phpinfo() test confirmed that execution functions such as system, exec, shell_exec, and proc_open were available.
Action: with a listener ready, uploaded a PHP file and requested it over HTTP.
nc -lvnp <LISTENER_PORT>curl http://<PRIMARY_VHOST>/tiny/uploads/<UPLOADED_PHP>The request returned a shell as the web-service account:
uid=33(www-data) gid=33(www-data) groups=33(www-data)Significance: an upload directory that executes server-side code converts administrative file access into code execution under the web-service account.
Result: command execution as the web-service account is established.
4. Local Configuration Review
Section titled “4. Local Configuration Review”Observation: local socket and nginx configuration inspection showed a loopback database listener and a second enabled site.
ss -tulpnls -la /etc/nginx/sites-enabled/tcp LISTEN 0 151 127.0.0.1:3306 0.0.0.0:*default<SECONDARY_SITE>Significance: reading web-server configuration exposes an application virtual host that was not reachable from initial external enumeration.
Result: a second application virtual host with login, signup, and ticket-checking functionality is identified.
5. WebSocket Ticket-Check SQL Injection
Section titled “5. WebSocket Ticket-Check SQL Injection”Observation: the ticket check is sent as a WebSocket message to port 9091, and its identifier field is SQL-injectable.
Action: proxied HTTP requests into the WebSocket message format so the SQL-injection tool could target the endpoint.
sqlmap-websocket-proxy -u ws://<SECONDARY_VHOST>:9091 -d '{"id":"%param%"}' -H "Origin: http://<SECONDARY_VHOST>"sqlmap -u "http://localhost:<PROXY_PORT>/?param=1" --dumpDatabase: <APPLICATION_DATABASE>Table: <ACCOUNT_TABLE>| <ID> | <LAB_USER_EMAIL> | <LAB_USER_PASSWORD> | <LAB_USER> |Significance: the injectable identifier reached the backing database and disclosed an account credential; the WebSocket transport received the same lack of input handling as an HTTP parameter.
Result: a credential pair for <LAB_USER> is recovered from the application database.
6. SSH Access as the Lab User
Section titled “6. SSH Access as the Lab User”Observation: the recovered credential authenticates the lab user over SSH.
ssh <LAB_USER>@<TARGET_HOST># password: <LAB_USER_PASSWORD><LAB_USER>@<TARGET_HOST>:~$Significance: the secret disclosed by the web application also satisfies host authentication, so the database disclosure becomes an interactive host session.
Result: the recovered credential is validated through SSH and an authenticated shell as <LAB_USER> is obtained.
7. Delegated doas Rule Discovery
Section titled “7. Delegated doas Rule Discovery”Observation: a custom doas binary is present, and its configuration permits a passwordless root invocation of dstat.
find / -name "doas*" 2>/dev/null/usr/local/etc/doas.confThe configuration grants the permission:
permit nopass <LAB_USER> as root cmd /usr/bin/dstatSignificance: the rule delegates root execution of a single program, so the effective privilege depends on that program’s behavior rather than its command name.
Result: a passwordless root doas rule for dstat is identified.
8. Root via dstat Plugin Loading
Section titled “8. Root via dstat Plugin Loading”Observation: dstat loads external Python plugins from directories including /usr/local/share/dstat/.
Action: wrote a plugin into a directory dstat loads, then invoked the permitted program by plugin name through the doas rule.
echo '<PLUGIN_CODE>' > /usr/local/share/dstat/dstat_<PLUGIN_NAME>.pydoas -u root /usr/bin/dstat --<PLUGIN_NAME># whoamirootSignificance: because dstat executes plugin code while running as root, the delegated rule amounts to arbitrary root code execution.
Result: a root context is obtained through the permitted dstat command.
Challenges and Decisions
Section titled “Challenges and Decisions”| Challenge | Decision | Rationale |
|---|---|---|
| The ticket check is transported as a WebSocket message, which the selected SQL-injection tool does not speak natively | Proxied HTTP requests into the WebSocket message format | Needed to drive the tool against the endpoint |
The doas rule permits only dstat, not a shell |
Invoked a plugin loaded by the permitted program | The binary’s extension mechanism, not its command name, determined the available privilege |
Outcome
Section titled “Outcome”The evidence establishes default-credential file-manager access, code execution as the web-service account, a credential recovered through WebSocket SQL injection and validated over SSH, and root through dstat plugin loading under a delegated doas rule.
Lessons and Recommendations
Section titled “Lessons and Recommendations”Each finding pairs the observed root cause with its demonstrated impact and a prioritized action. The actions are recommendations; none was validated in the lab.
- Default credentials on administrative software. Known default credentials granted full file-management access. Recommendation: remove or rotate default credentials before deployment and restrict administrative interfaces to trusted access paths. Detection: alert on logins using vendor-default accounts and on administrative interface access from unexpected sources.
- Executable upload directory.
/tiny/uploadsexecuted uploaded PHP, giving code execution as the web-service account. Recommendation: store uploads outside executable paths and explicitly disable server-side execution in upload directories. Detection: alert on newly written executable files under the web root. - Unvalidated WebSocket endpoint. The ticket-checking message reached the database without input handling, disclosing an account credential. Recommendation: apply parameterized queries and input validation to WebSocket handlers as well as HTTP routes. Detection: log and review WebSocket payloads for injection patterns.
- Over-broad
doasdelegation. A passwordless root rule fordstatallowed arbitrary code execution through its plugin loading. Recommendation: reviewsudoanddoasallowlists against the full behavior of each permitted program, and exclude binaries that load user-controlled extensions. Detection: audit delegation rules for plugin-capable or scriptable binaries and monitor plugin directories for unexpected files.
References
Section titled “References”- Hack The Box — Soccer (retired machine)
- Tiny File Manager (default-credentials file manager)
- sqlmap (SQL injection detection and exploitation)
- sqlmap-websocket-proxy (HTTP-to-WebSocket proxy for sqlmap)
- RustScan (fast port scanner)
- feroxbuster (content discovery)
- dstat (system statistics tool with external plugins)
- doas (OpenBSD execute-as delegation)