[Easy] Two Million — HackTheBox
Two Million is an easy level box which was released because of the celebration of the 2 million user milestone. This box features the older version of HackTheBox (the version I used when I first joined), it has the old CTF challenge. This box did surprise me with nostalgia from that CTF challenge. After finishing the invite code challenge, this account is used to enumerate and elevate the user to admin. With admin you can preform a cmd injection in the VPN file generation. Then you can fully leverage the shell via enumerating the environment variables file, which can be abused for password reuse. Finally to gain root, the system kernel is found to be outdated which then leads to CVE-2023–0386.
Note: This is my first HTB Writeup, I may have made some mistakes, forgive me if so, nevertheless please respect me if this helped you!
@V37R1X — https://app.hackthebox.com/profile/496941
Enumeration
Nmap scan
Ports 22 and 80 are open therefore you can add 2million.htb
to /etc/hosts
Fuzzing Endpoints
Fuzzing endpoints helps understand what the website is going to have to discover more interesting endpoints.
Website
Skimming through the website we can identify a few things, we will have to solve a challenge to get onto the platform — As any platform should do to test learners.
Here we can see that you should solve the entry level challenge which is found on the /invite
endpoint.
This part of the website seems to look like the normal old invite code challenge. Lets investigate the code! Taking a further look into the source code we can identify that the second function of the code shows a POST
request towards /api/v1/invite/verify
to check if the code is valid or invalid.
As well as this code inline script tags, there is another code inside inviteapi.min.js
which is loaded within the website.
That code is obfuscated therefore we can deobfuscate the code using online tools like de4js.
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)
}
})
}
In this code there are two functions, first one is similar to the last code we saw and the second one is interesting, the endpoints are also interesting. We can make a POST
request to that endpoint. Let’s go forth using burp.
This output is basically encrypted via Caesar Cipher (ROT13). The enctype
, shows that it is ROT13. This message decrypts as:
Note: I used CyberChef to decrypt this text.
Recipe: https://cyberchef.org/#recipe=ROT13(true,true,false,13)&input=VmEgYmVxcmUgZ2IgdHJhcmVuZ3IgZ3VyIHZhaXZnciBwYnFyLCB6bnhyIG4gQ0JGRyBlcmRocmZnIGdiIFwvbmN2XC9pMVwvdmFpdmdyXC90cmFyZW5ncg
So it is telling us to generate the invite code using that /generate
endpoint in the v1 API. Let’s carry on:
We get a code, which is encoded in base64
Note: This is encoded not encrypted, two different words which have different meaning.
We have now successfully generated the code to login! We can register as yuma
for username and yuma@2million.htb
for the email and of course a password. After that is done we get redirected to /register
.
After logging in sucessfully we get redirected to /home
The /access
page is very useful due to the fact we can download and regenerate the vpns to use HTB (like we normally do).
Clicking on getting the connection pack, we can see it is actually an openvpn file.
Requesting to /api
we can read versions.
Requesting towards /api/v1
we can enumerate all endpoints. We can check if we are the admin
user.
Looks like we are not admin, therefore we could switch requests to POST as well as request to the vpn generate endpoint
On this we get 401, now lets try the last one.
We do not get either errors, therefore we can play around/modify with the endpoint. It also says I have the invalid content type, which is correct because I used x-www-form-urlencoded instead of json.
Now I have changed this, and it is asking for the email
parameter, we can modify the request.
We are now missing another parameter this time it’s called is_admim
. This is what I believe a check to check if you are present as admin. Which normally is a Boolean type.
Although, it is not true, false its 0 or 1 this time. We can modify this.
Now lets check if we are actually admin.
Now are are truly admin, we can move to the Foothold stage.
Foothold
We can now try and generate a vpn file as admin.
Weirdly, it states we have to add a parameter with a username.
We can see that a VPN configuration file was generated for the user test and printed to us after issuing the aforementioned command. Given that the exec or system PHP functions are being used to create this VPN, there may not be enough filtering in place to prevent malicious code from being injected into the username field and gaining command execution on the distant machine.
By inserting the command ;whoami;
after the username, let’s test this supposition.
Lets chuck our listener up and rolling!
We can base64 encode this payload to use base64 to execute the command.
Note: If this payload does not work you can use mkfifo.
Now for the moment of truth…
www-data has been claimed!! On to the next stage which is lateral movement.
Lateral Movement (www-data -> user)
We have another user to claim which is admin.
The current file system has an .env
file which shows passwords for users. We can use password reuse to gain user.
We can exit the shell and ssh as admin.
User
Root
It shows we have mail. Lets check /var/mail/admin
for more information.
We can skim through this mail and use the BOX method to see the key points on this message which is OverlayFS/FUSE and kernel CVEs.
Searching through Google we can see this CVE https://nvd.nist.gov/vuln/detail/CVE-2023-0386
This box is 5.15.70, we can enumerate further to see release stages.
Which leads us to this POC: https://github.com/xkaneiki/CVE-2023-0386
We can clone the repo and tar it to make it easier to transfer.
We put up a server to transport the file and then curl it through. Then unarchive the achieve.
Then we follow the POC, shown in Github.
Keeping it running and spawning another ssh shell, we get root.
Surprise
We can see thank_you.json.
The data seems url encoded, so lets pull up cyberchef.
We can see that its both base64
and xor
knowing the key being HackTheBox
.
Final Recipe: https://cyberchef.org/#recipe=From_Hex('Auto')&input=JTdCJTIyZW5jb2RpbmclMjI6JTIwJTIyaGV4JTIyLCUyMCUyMmRhdGElMjI6JTIwJTIyN2IyMjY1NmU2MzcyNzk3MDc0Njk2ZjZlMjIzYTIwMjI3ODZmNzIyMjJjMjAyMjY1NmU2MzcyNzA3OTc0Njk2ZjZlNWY2YjY1NzkyMjNhMjAyMjQ4NjE2MzZiNTQ2ODY1NDI2Zjc4MjIyYzIwMjI2NTZlNjM2ZjY0Njk2ZTY3MjIzYTIwMjI2MjYxNzM2NTM2MzQyMjJjMjAyMjY0NjE3NDYxMjIzYTIwMjI0NDQxNTE0MzQ3NTg1MTY3NDI0MzQ1NDU0YzQzNDE0NTQ5NTE1MTczNTM0MzU5NzQ0MTY4NTUzOTQ0Nzc2ZjY2NGM1NTUyNzY1MzQ0Njc2NDYxNDE0MTUyNDQ2ZTUxNjM0NDU0NDE0NzQ2NDM1MTQ1NDIzMDczNjc0MjMwNTU2YTQxNTI1OTZlNDY0MTMwNDk0ZDU1Njc0NTU5Njc0OTU4NGE1MTUxNGU0ODdhNzM2NDQ2NmQ0OTQzNDU1MzUxNDU0NTQyMzgzNzQyNjc0MjY5NDI2ODVhNmY0NDY4NTk1YTY0NDE0OTRiNGU3ODMwNTc0YzUyNjg0NDQ4N2E3MzUwNDE0NDU5NDg0ODU0NzA1MDUxN2E3NzM5NDg0MTMxNjk0MjY4NTU2YzQyNDEzMDU5NGQ1NTY3NTA0YzUyNWE1OTRiNTEzODQ4NTM3YTRkNjE0MjQ0NTk0NzQ0NDQzMDQ2NDI2YjY0MzA0ODc3NDI2OTQ0NDIzMDZiNDI0MTQ1NWE0ZTUyNzc0MTU5Njg3MzUxNGM1NTQ1NDM0MzQ0Nzc0MjQxNDQ1MTRiNDY1MzMwNTA0NjMwNzMzNzQ0NmI1NTc3NDM2ODZiNzI0MzUxNmY0NjRkMzA2ODU4NTk2NzQ5NTI0YTQxMzA0YjQyNDQ3MDQ5NDY3OTYzNDM0NzU0NmY0YjQxNjc2YjM0NDQ1NTU1MzM0ODQyMzAzNjQ1NmI0YTRjNDE0MTQxNGQ0ZDU1Mzg1MjRhNjc0OTUyNDQ2YTQxNDI0Mjc5MzQ0YjU3NDMzNDQ1NDE2ODM5MzA0ODc3NmYzMzQxNzg3ODZmNDQ3Nzc3NjY2NDQxNDE0NTRlNDE3MDU5NGI2NzUxNDc0MjU4NTE1OTQzNmE0NTYzNDU1MzZmNGU0MjZiNzM2YTQxNTI0NTcxNDE0MTMwMzg1MTUxNTk0YjRlNzc0MjQ2NDk3NzQ1NjM2MTQxNTE1NjQ0Njk1OTUyNTI1MzMwNDI0ODU3Njc0ZjQyNTU3Mzc0NDI3ODQyNzM1YTU4NDk0ZjQ1Nzc3NzQ3NjQ0Mjc3NGU0YTMwMzg0ZjRjNTI0ZDYxNTM3YTU5NGU0MTY5NzM0MjQ2Njk0NTUwNDI0NTY0MzA0OTQxNTE2ODQyNDM3NzY3NDI0MzQ1NDU0YzQ1Njc0ZTQ5Nzg3ODU5NGI2NzUxNDc0MjU4NTE0YjQ1NDM3MzQ0NDQ0NzY3NTU0NTc3NTEzNjUzNDI0NTcxNDM2YzY3NzE0MjQxMzg0MzRkNTEzNTQ2NGU2NzYzNWE1MDQ1NDU0OTQyNTQ3MzY2NDM1MzYzNGM0ODc5MzE0MjQ1NDE0ZDMxNDc2Nzc3NzM0MzQ2NTI2ZjQxNjc3NzQ4NGY0MTZiNDg0YzUyMzA1YTUwNDE2NzRkNDI1ODY4NDk0MjQzNzc0YzU3NDM0MTQxNDQ1MTM4NmU1MjUxNmY3MzU0NzgzMDc3NDU1MTU5NWE1MDUxMzA0YzQ5NTE3MDU5NGI1MjRkNDc1MzdhNDk2NDQzNzk1OTRmNDY1MzMwNTA0Njc3NmYzNDUzNDI0NTc0NTQ3NzY3NzQ0NTc4NDE0NTRmNjc2YjRhNTk2NzM0NTc0YzQ1NDU1NDQ3NTQ3MzRmNDE0NDQ1NjM0NTUzNjM1MDQxNjc2NDMwNDQ3ODYzNzQ0NzQxNzc2NzU0MzA0ZDJmNGY3NzM4NDE0ZTY3NjM2NDRmNmIzMTQ0NDg0NDQ2NDk0NDUzNGQ1YTQ4NTc2NzQ4NDQ0MjY3Njc0NDUyNjM2ZTQzMzE2NzcwNDQzMDRkNGY0ZjY4MzQ0ZDRkNDE0MTU3NGE1MTUxNGU0ODMzNTE2NjQ0NTM2MzY0NDg1NzY3NDk0NDUxNTUzNzQ4Njc1MTMyNDI2ODYzNmQ1MTUyNjM0NDRhNjc0NTU0NGE3ODc4NTk0YjUxMzg0ODUzNzk2MzQ0NDQ0MzM0NDQ0MzMyNjc0MTQ1NTEzNTMwNDE0MTZmNzM0MzY4Nzg2ZDUxNTM1OTRiNGU3NzQyNDY0OTUxNjM1YTRhNDEzMDQ3NDI1NDRkNGU1MjUzNDU0MTQ2NTQ2NzRlNDI2ODM4Nzg0NDQ1NmM2OTQzNjg2YjcyNDM1NTRkNDc0ZTUxNzM0ZTRiNzc0NTY0NjE0MTQ5NGQ0MjUzNTU2NDQxNDQ0MTRiNDg0NzUyNDI0MTY3NTU3NzUzNDE0MTMwNDM2NzZmNzg1MTUyNDE0MTUwNTE1MTRhNTk2NzRkNjQ0YjUyNGQ0ZTQ0NmE0MjQ5NDQ1MzRkNjM1NzQzNzM0ZjQ0NTIzODZkNDE1MTYzMzM0Nzc4MzA3MzUxNTI2MzQ1NjQ0Mjc3NGU0YTMwMzg2MjRhNzczMDUwNDQ2YTYzNjM0NDQ0NTE0YjU3NDM0NTUwNDY3NzM0MzQ0MjQxNzc2YzQzNjg1OTcyNDI0NTRkNjY1MDQxNmI1MjU5Njc2YjRlNGM1MTMwNTE1Mzc5NDE0MTQ0NDQ0NjUwNDQ2OTQ1NDQ0NTUxNmYzNjQ4NDU1NTY4NDE0MjU1NmM0NjQxMzA0MzQ5NDI0NjRjNTM0NzU1NzM0YTMwNDU0NzQzNmE2MzQxNTI1MzRkNDI0ODQ3Njc0NTQ2NTEzNDZkNDU1NTU1NzY0MzY4NTU3MTQyNDI0NjRjNGY3NzM1NDY0ZTY3NjM2NDYxNDM2YjQzNDM0NDM4Mzg0NDUzNjM3NDQ2N2E0MjQyNDE0MTUxMzU0MjUyNDE3MzQyNjc3Nzc4NTQ1NTRkNjY1MDQxNmI0YzRiNTUzODQyNGE3ODUyNDQ0NDU0NzM2MTUyNTM0MTRiNDU1MzU5NDc1MTc3NzAzMDQ3NDE1MTc3NDczMTY3NmU0MjMwNGQ2NjUwNDE0NTU3NTk2NzU5NTc0Yjc4NGQ0NzQ0N2EzMDRiNDM1MzY0NTA0NTY5NjM1NTQ1NTE1NTc4NDU1NTc0Njk0ZTY4NjMzOTQ1MzA0ZDQ5NGY3NzU5NTI0ZDQxNTk2MTUwNTI1NTRiNDI0NDZmNjI1MjUzNmY0ZjQ0NjkzMTQyNDU0MTRkMzE0NzQxNDE2ZDU0Nzc3NzY3NDI0NTRkNjQ0ZDUyNmY2MzU5Njc2YjVhNGI2ODRkNGI0MzQ4NTE0ODQxMzI0OTQxNDQ1NDcwNDI0NTc3NjMzMTQ4NDE0ZDc0NDg1MjU2NmY0MTQxMzA1MDY0NDE0NTRjNGQ1MjM4NTI0ZjY3NTE0ODUzNzk0NTYyNTI1NDU5NDE1NzQzNzM0ZjQ0NTIzODM5NDI2ODQxNmE0MTc4NTE3ODUxNTE2ZjQ2NGY2NzYzNTQ0OTc4NzM2NDYxNDE0MTRlNDQzMzUxNGU0NTc5MzA0NDQ0NjkzMTUwNTE3YTc3Nzg1MzQxNTE3NzQzNmM2NzY4NDQ0MTM0NGY0ZjY4NzM0MTRjNjg1YTU5NGY0MjRkNGQ0ODZhNDI0OTQzNjk1MjUwNDQ3OTQxNDE0NjMwNzM2YTQ0NTU1NTcxNDQ2NzM0NzQ1MTUxNDk0OTRlNzc2MzQ5NGQ2NzRkNTI0Zjc3NmI0NzQ0MzM1MTYzNDM2OTU1NGI0NDQzNDE0NTQ1NTU2NDMwNDM1MTczNmQ1NDc3Mzg3NDUxNTE1OTRiNGQ3NzMwNTg0YzY4NWE1OTRiNTEzODU4NDE2YTYzNDI0NjUzNGQ2MjQ4NTc2NzU2NDM3NzM1MzA0Mzc3NmYzMzQxNTE3NzZiNDI0MjQxNTk2NDQxNTU0ZDRjNjc2ZjRjNTA0MTM0NGU0NDY5NjQ0OTQ4NDM2MzYyNTc0NDc3NGY1MTc3NjczNzQyNTE0MjczNWE1ODQ5NDE0MjQyNDU0ZjYzNzg3NDQ2NGU2NzQyNTk1MDQxNmI0NzUzN2E2ZjRlNDg1NDVhNTA0Nzc5NDE0MTQ1NzgzODc4NDc2YjZjNjk0NzQyNDE3NDQ1Nzc1YTRjNDk3NzMxNDY0ZTUxNTk1NTRhNDU0NTQxNDI0NDZmNjM0NDQzNzc2MTQ4NTc2NzU2NDQ0NTczNmI0ODUyNTk3MTU0Nzc3NzY3NDI0NTRkNGE0Zjc4MzA0YzRhNjczNDRiNDk1MTUxNTE1MzdhNzM0ZjUyNTM0NTU3NDc2OTMwNTQ0NTQxMzQzMzQ4NTI2MzcyNDc3NzQ2NmI1MTUxNmY0NjRhNzg2NzRkNGQ0MTcwNTk1MDQxNmI0NzUzN2E2ZjRlNDg1NDVhNTA0ODc5MzA1MDQyNjg2YjMxNDg0MTc3NzQ0MTU2Njc2ZTQyMzA0ZDRmNDk0MTQxNGQ0OTUxMzQ1NTYxNDE2YjQzNDM0NDM4NGU0NjdhNDY0NDU3NDM2YjUwNDIzMDczMzM0NzY3NDE2YTQ3NzgzMTZmNDE0NTRkNjM0Zjc4NmY0YTRhNmIzODUwNDk0MTUxNTI0NDZlNTE0NDQzNzkzMDU5NDY0MzMwNDY0MjQxMzUzMDQxNTI1YTY5NDQ2ODczNzI0MjQyNDE1OTUwNTE2ZjRhNGEzMDM4NGQ0YTMwNDU0MzQyN2E2ODQ3NjIzMDY3MzQ0NTU0Nzc0YTUxNzczODc4NDQ1MjU1NmU0ODQxNzg2ZjQyNjg0NTRiNDk0MTQ1NTI0ZTc3NzM2NDVhNDc3NDcwNTA3YTc3NGU1MjUxNmY0ZjQ3Nzk0ZDMxNDM3NzM0NTc0Mjc4MzE2OTRmNzgzMDcwNDQ0MTNkM2QyMjdkJTIyJTdE
Thanks for making this box and congrats on 2 million users!