Cap (Hack the Box)
Cap is an Active machine on Hack the Box so this writeup will not be posted live to this website until a later date. Some information about the system:
- OS: Linux
First things first, let’s start off with an nmap scan.
I shortened some of the nmap output ignoring the remaining output for the HTTP service as well as the OS fingerprinting.
The target is an Ubuntu OS as indicated by the service version information for the SSH service. Other interesting things of note is that the server hosting the web service on port 80 is a Gunicorn server which means the likelihood of the back-end language being Python is high.
There are 3 open ports:
- 21 (FTP)
- 22 (SSH)
- 80 (HTTP)
Let’s enumerate some of these services a bit more.
When we first browse to the landing page, we come across a security dashboard providing statistics on a few security events.
If we expand the left-hand side “hamburger” menu and the drop down under Nathan, we are presented with several hyperlinks.
The links under the Nathan drop down were empty hyperlinks that did not lead anywhere. However, each of the tabs on the “hamburger” menu provided useful information about the system.
The title IP Config pretty well explains its purpose displaying the interface configuration of the system.
This target is not dual-homed and it contains a single interface that we are accessing so there is not much to look at here.
The Netstat section is also just as clear on its purpose.
There is a significant amount of output here as well but there was not much of interest. I also don’t have much experience reading netstat output unless it is the standard
netstat -tulnp command.
Hovering over the Security Snapshot tab, we notice that the application is pointing us the
/capture endpoint. Once I clicked on this tab, the application hung for a few seconds before displaying a summary of packet information.
In this situation, there is not much useful information presented as there are no packets. If I download the file, it saves to the filesystem as 3.pcap with no packets captured. That probably explains the 0 values presented to us for each field in the Dashboard.
However, if we notice the url, the application redirected to us to
/data/3. The application is probably capturing packets and saving them as numerical ID’s and subsequently available to download as
<id>.pcap. So, what if we modify the ID value to access other packet captures. The packet captures with ID 1 and 2 did not contain any packets either but the packet capture with ID 0 had plenty.
The file, 0.pcap, captured communication between nathan and several of the services available on the target. One of the series of packets captured nathan’s authentication to the FTP server in cleartext.
Fantastic! We have a potential entry point into the system!
Let’s try out these creds.
Great! The credentials were in fact valid and dropped us into nathan’s home directory.
At this point, I spent a significant amount of time searching through the file system for potential SSH private/public keys, and the application source code.
Maybe we are able to drop a reverse shell written in Python into the /var/www/html directory that Gunicorn is serving the application from. No luck there!
Checking out the application source code, I saw the app.py file that contained all of the endpoints written in Flask (Python web micro-framework) and one of the functions stood out to me.
There weren’t many conclusions I could draw from this so I quickly moved on but I will address this more in the Reflection section.
At this point, I had nothing to go off of. I was still trying to assess other vectors to gain access through the FTP server. At the same time, I was working on this box with my friend. He had already gained access so I asked him what his vector was and he told me SSH. And then it hit me like a ton of bricks; the creds for the FTP server were the same as the SSH service.
SMH. But yay!
Now that we have our initial foothold, let’s grab the user.txt flag.
Since I was working on the box with my friend, he had already ran through the Linpeas (privilege escalation enumeration) script, and we combed through any potential vectors.
One of the ones that he noticed was that Python had the cap_setuid capability set. Interestingly enough, I had encountered the same privesc vector with Perl on a TryHackMe box.
With Python having the cap_setuid capability set, we are able to abuse this courtesy of a command from GTFObins 1.
Now, we can use this command to escalate our privileges and get the root flag!
And, we have completed this box.
Find all files with capabilities set
getcap -r / 2>/dev/null
Privilege Escalation with Python Capability
If the Python binary has the cap_setuid capability set, use
python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
to escalate your privileges.
After reflecting on this box, I noticed a few things that would have made the privilege escalation technique a bit more obvious.
The Security Snapshot tab was capturing the traffic for 5 seconds and generating a packet cpature file. However, capturing traffic is a root privilege which the application was performing. Unless the application was running as root, this isn’t possible without providing some root privileges to the application.
The code comments in the /capture endpoint of the image that I posted earlier highlights this fact since nathan applied a hacky trick with the setuid(0) capability in order to capture the traffic.
This further highlights one of my weaknesses which is building a mental landscape of an application’s functionality. This is a vital step once you have fully enumerated an application and something to focus on in the future.
Overall, a very enjoyable room on HackTheBox and definitely one of the easier ones that I would recommend.