I recently managed to complete another machine on Hack the Box, and in this post, I want to walk you through the steps I took to solve it. Luanne got released as an easy difficulty NetBSD machine. I can’t entirely agree with this difficulty level, as many others have also given this machine a lousy rating and got some critique in the forums. Nonetheless, I really enjoyed solving this machine. For me, the main problem was my lack of experience with BSD systems. It made me waste a lot of time getting my Linux reverse shell knowledge ported over to BSD. But forgetting that I was solving a BSD machine halfway through the challenge also didn’t help! Let’s dive into the machine and start our initial discovery with a nmap scan. The command will enumerate all versions -sV, run all default scripts -sC, and store the output in nmap.txt to refer back to it later.
At this point, I kicked off another scan in the background to scan all ports with -p-, but that didn’t turn up any new results. You can see that the target host has ports 22, 80 and 9001 open and is using NetBSD. A few other things to note is the robots.txt file behind the service running on port 80 and that both services require authentication.
I’m not sure what Medusa httpd or Supervisor process manager is. So I’m going to focus my attention first on the service running behind port 80. Opening up Firefox, we get greeted with a basic auth login prompt.
Cancelling the login prompt, I noticed something interesting. In the returned response, we get a reference to something running on localhost 127.0.0.1:3000. Probably an interesting service to take a deeper look at when I get a foothold on the machine!
A gobuster scan gobuster dir -u http://10.10.10.218 -w /opt/SecLists/Discovery/Web-Content/raft-small-words.txt -o 80-root.txt didn’t show anything interesting other than the 401 on /. Looking at robots.txt gives the following:
We already know that /weather is giving a 404 because it wasn’t showing up in our gobuster scan. But the comment indicates that this endpoint could still return something. So I kicked off another gobuster scan, this time focusing on the /weather endpoint.
So the weather endpoint has /forecast that does return a 200. Let’s play around with curl and try to get a better understand of how this API works:
It seems the API is relatively straightforward. Given a parameter city, it will provide you with the weather forecast for that city. This city parameter is something I can control and thus want to play around with next. Lets see see if we can get some weird results by adding special characters. I always like to manually add the following characters (%, " and ') because I find they often yield interesting results.
Not sure what happened when injecting the percentage sign. It seems that it invalidated the whole query. But hard to say, for now, let’s keep that in mind for later. Because using a single quote returns a Lua error message. I have written some Lua code in the past but am by all means no expert in this language. I will need to do some research to better understand what constructs the language/runtime offers to get an RCE.
This first article was fascinating, especially the following section, which gave me a good overview of how to construct my initial exploit.
Continuing on this idea, I would like to make sure I can get some basic injection working. But for this, I’m going to move on to Burp Suite so I can have better control over the payload I’m going to inject. Playing around, I managed to cobble together a working payload:
Do notice the --, which is a comment in Lua and is required to get this exploit working. Adding a comment to the end of a payload is always an easy escape hatch to get an exploit to work. We can see it is working because the output of the id comment got appended in the response. We now know that we can execute commands as the _httpd user on the host.
At this point, I got stuck for some time trying to get a reverse shell up and running. I didn’t manage to get any of my default reverse shells working. I even tried writing the payload in Lua, but that didn’t work because of missing modules. Taking a step back, I remembered again that this target host was a BSD system. Searching around for a BSD specific reverse shell, I bumped into this repo.
And I’ve got a shell:
The directory seems to have a .htpasswd, which contains a UNIX md5 hash. We can verify this by dumping example hashes from hashcat and grep for the first couple of characters of the hash:
This shows what mode we should use to crack the password:
Hashcat appends the cracked password to the end of the line. The cracked password and username give access to the service running on port 80. But there is nothing much to be gained here:
I also tried to get access to the service running on port 9001, but the credentials didn’t seem to work for this service. Pretty early on, I noticed that Nginx was proxying to something on localhost. Let’s have a look and see what is running on this box:
There seem to be two services running on localhost, one on port 3000 and one on 3001. They both seem to be running the same httpd binary and weather service. But when looking closely, they seem to be using different scripts and command-line flags. It’s time to have a deeper look into this httpd binary:
With the help of my search engine, I bumped into this NetBSD httpd manpage. Let’s have a look and try to piece together what each argument does:
Argument
Description
-u
Enables the transformation of Uniform Resource Locators of the form /~user/ into the directory ~user/public_html
-X
Enables directory indexing
-s
Forces logging to be set to stderr always.
-i
Sets the address to be used.
-I
Causes httpd to use the given port instead of the default one.
-U
Causes httpd to switch to the given user
The interesting thing here is the -u flag, which allows access to user directories by using a URL in the form of /~user/. -U, on the other hand, runs the service under a different user. So let’s have a look at the service running on port 3001. It requires some form of authentication, but we already managed to crack a password, lets see if that one works:
A directory listing, showing an id_rsa file in r.michaels home directory. I downloaded the key with curl -u webapi_user:iamthebest localhost:3001/~r.michaels/id_rsa and used ssh to login into the account from my local machine:
And that’s the user flag right there /home/r.michaels/user.txt. This directory contains everything required to escalate privileges to the root account. This took me a bit of time to figure out. Initially, I started looking at privilege escalation detection scripts. But looking closely, I noticed the .gnupg contains a key, and the backups directory has an encrypted file.
Some research online reveals that on NetBSD the tool netpgp can be used used to decrypt files:
Decrypting the file to the tmp directory and extracting it shows another .htpasswd file. Let’s also try and crack it in the same manner as before by copying the hash to our local machine and run hashcat on it.
Another password cracked! This time it returns littlebear, but it seems that this password is supposedly for the same webapi_user. On a BSD system, doas is the equivalent of sudo on Linux. So let’s see if r.micheals is allowed to run programs as root:
Alright, we have root access with this password. Suppose you are in a situation where you want to play on the safe side, not set off any alarms, … . It’s possible first to check the doas.conf file, similar to the sudoers file on Linux; it will show if a user has sudo access and what access is allowed. I skipped this step because I couldn’t locate the doas.conf file on this NetBSD system and didn’t want to waste much more time. Or use a privilege escalation suite which could probably also detect this for you.
And that’s the root flag /root/root.txt, which concludes my walkthrough.
Conclusion
This was a pretty fun challenge to solve. But I do think I got lucky a couple of times here there. I, for example, never dug into the service running on port 9001. When reading the official walkthrough afterwards, the Medusa Supervisor Process Manager running behind this port was configured using the default credentials of user and password 123. This application gives an overview of running processes and reveals that Lua script is running on this machine. From what I understood, this service would have no other use than that. So I got slightly lucky figuring out what language was used because of the error message leaking this back to me.
I always learn something new by solving these machines. This time I learned lots of new stuff about BSD systems and NetBSD in general. Something I would others rarely run in to or use in my day to day life. I am already looking forward to sharing my following walkthrough and learnings with you all.