Jump Ahead: Enum – User – Root – Resources
TL;DR;
To solve this machine, we begin by enumerating open ports – finding ports 21
, 22
, and 80
open. On the webserver, we are able to exploit an Insecure Direct Object Reference (IDOR) vulnerability
to obtain system credentials as the nathan
user. Using the credentials, we are able to SSH into the machine, and read user.txt
. Through automated, local enumeration, we learn a system package is incorrectly configured to allow setuid
. Using this knowledge, we are able to exploit the package to get a shell as root
– gaining access to root.txt
.
Enumeration
Like all machines, we begin by enumerating open ports – finding ports 21
, 22
, and 80
open.
$ sudo nmap -v -p- $RHOST
[...]
$ sudo nmap -p21,22,80 -sV -A -oA enum/nmap/tcp-scripts $RHOST
# Nmap 7.91 scan initiated Sat Jun 5 19:45:34 2021 as: nmap -p21,22,80 -sV -A -oA enum/nmap/tcp-scripts 10.129.119.0
Nmap scan report for 10.129.119.0
Host is up (0.047s latency).
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
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 NOT FOUND
| Server: gunicorn
| Date: Sun, 06 Jun 2021 00:45:49 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: Sun, 06 Jun 2021 00:45:44 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: Sun, 06 Jun 2021 00:45:44 GMT
| Connection: close
| Content-Type: text/html; charset=utf-8
| Allow: HEAD, GET, 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 'Invalid HTTP Version: 'RTSP/1.0''
| </body>
|_ </html>
|_http-server-header: gunicorn
|_http-title: Security Dashboard
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port80-TCP:V=7.91%I=7%D=6/5%Time=60BC1ABB%P=x86_64-pc-linux-gnu%r(GetRe
SF:quest,2FE5,"HTTP/1\.0\x20200\x20OK\r\nServer:\x20gunicorn\r\nDate:\x20S
SF:un,\x2006\x20Jun\x202021\x2000:45:44\x20GMT\r\nConnection:\x20close\r\n
SF:Content-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x201938
SF:6\r\n\r\n<!DOCTYPE\x20html>\n<html\x20class=\"no-js\"\x20lang=\"en\">\n
SF:\n<head>\n\x20\x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20
SF:<meta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\x20\x
SF:20\x20\x20<title>Security\x20Dashboard</title>\n\x20\x20\x20\x20<meta\x
SF:20name=\"viewport\"\x20content=\"width=device-width,\x20initial-scale=1
SF:\">\n\x20\x20\x20\x20<link\x20rel=\"shortcut\x20icon\"\x20type=\"image/
SF:png\"\x20href=\"/static/images/icon/favicon\.ico\">\n\x20\x20\x20\x20<l
SF:ink\x20rel=\"stylesheet\"\x20href=\"/static/css/bootstrap\.min\.css\">\
SF:n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20href=\"/static/css/font
SF:-awesome\.min\.css\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20h
SF:ref=\"/static/css/themify-icons\.css\">\n\x20\x20\x20\x20<link\x20rel=\
SF:"stylesheet\"\x20href=\"/static/css/metisMenu\.css\">\n\x20\x20\x20\x20
SF:<link\x20rel=\"stylesheet\"\x20href=\"/static/css/owl\.carousel\.min\.c
SF:ss\">\n\x20\x20\x20\x20<link\x20rel=\"stylesheet\"\x20href=\"/static/cs
SF:s/slicknav\.min\.css\">\n\x20\x20\x20\x20<!--\x20amchar")%r(HTTPOptions
SF:,B3,"HTTP/1\.0\x20200\x20OK\r\nServer:\x20gunicorn\r\nDate:\x20Sun,\x20
SF:06\x20Jun\x202021\x2000:45:44\x20GMT\r\nConnection:\x20close\r\nContent
SF:-Type:\x20text/html;\x20charset=utf-8\r\nAllow:\x20HEAD,\x20GET,\x20OPT
SF:IONS\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,121,"HTTP/1\.1\x20
SF:400\x20Bad\x20Request\r\nConnection:\x20close\r\nContent-Type:\x20text/
SF:html\r\nContent-Length:\x20196\r\n\r\n<html>\n\x20\x20<head>\n\x20\x20\
SF:x20\x20<title>Bad\x20Request</title>\n\x20\x20</head>\n\x20\x20<body>\n
SF:\x20\x20\x20\x20<h1><p>Bad\x20Request</p></h1>\n\x20\x20\x20\x20Invalid
SF:\x20HTTP\x20Version\x20'Invalid\x20HTTP\x20Version:\x20'RTSP/
SF:1\.0''\n\x20\x20</body>\n</html>\n")%r(FourOhFourRequest,189,
SF:"HTTP/1\.0\x20404\x20NOT\x20FOUND\r\nServer:\x20gunicorn\r\nDate:\x20Su
SF:n,\x2006\x20Jun\x202021\x2000:45:49\x20GMT\r\nConnection:\x20close\r\nC
SF:ontent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20232\r
SF:\n\r\n<!DOCTYPE\x20HTML\x20PUBLIC\x20\"-//W3C//DTD\x20HTML\x203\.2\x20F
SF:inal//EN\">\n<title>404\x20Not\x20Found</title>\n<h1>Not\x20Found</h1>\
SF:n<p>The\x20requested\x20URL\x20was\x20not\x20found\x20on\x20the\x20serv
SF:er\.\x20If\x20you\x20entered\x20the\x20URL\x20manually\x20please\x20che
SF:ck\x20your\x20spelling\x20and\x20try\x20again\.</p>\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 22/tcp)
HOP RTT ADDRESS
1 43.24 ms 10.10.14.1
2 43.29 ms 10.129.119.0
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jun 5 19:47:59 2021 -- 1 IP address (1 host up) scanned in 144.90 seconds
From the results, nothing immediately stands out. Since FTP is running, we attempt to log in anonymously, however, this is disabled. Next, we enumerate port 80
using tools like gobuster
and nikto
. Unfortunately, these tools do not yield any useful results. Going to the webserver in a browser, we are presented with a website that appears to host several local network tools.
Clicking on the different links, we learn the “Security Snapshot” page generates a pcap
, the “IP Config” page shows the machine network interfaces, and the “Network Status” page prints a dump of netstat
.
Getting User
Since we did not find any further results from our automated tools, we decide to dig deeper into the web pages. Reflecting back on the “Security Snapshot” page, we generated a pcap, the URL path was /data/1
. This suggests a possible Insecure Direct Object Reference (IDOR) vulnerability may exist, if there is no authorization checks around the request. To test this, we can change this number, and monitor the results. In the case the object is invalid, we are redirected to the dashboard, however, when we set the number to “0”, we are given a valid capture file that we are able to download.
After we download the capture file, we open it in a packet analysis tool, such as Wireshark
. To help hunt for interesting information, we open the “Statistics” menu, and launch the Protocol Hierarchy
window. In it, we see there are FTP packets that were captured.
Since FTP is a clear-text protocol, we know there may be credentials captured that we can get. To check this, we set the display filter to “ftp”. Once we set the filter, within the first few packets, we see credentials for the nathan
user.
nathan
via packet analysisAs FTP on a linux machine is generally connected to a user account, we attempt the use the credentials to log in via SSH. Doing so, we get a shell as nathan
, and find user.txt
in his home folder.
user.txt
Getting Root
Since we now have local access to the machine as the nathan
user, we begin our local enumeration. Since we have credentials, we start by running sudo -l
to check if we are able to run any commands as another user. Unfortunately, this didn’t work, so we move on. As the webserver is not hosting a database, nor are credentials of any sort used, we decide to launch linpeas
to automate the enumeration for us. Looking through the results, we notice /usr/bin/python3.8
has the setuid
capability set.
This capability allows us to change the user ID of the python process. This means that we are able to execute python commands as any user, as long as we know their user ID. Since we know root
‘s user ID is “0”, we should be able to use python to get a shell as root
. To do this, we launch python, import the “os” module, change the user id, and execute bash. Once we do that, we now have a shell as root
, and can now read root.txt
.
root
, and read root.txt
Thank you for taking the time to read my write-up. I am interested in other ways this machine has been solved. Feel free to reach out to me and we can discuss it. Thanks!