
Writeup de la máquina Cap (HackTheBox · Linux · Fácil) por NeMeZIS (@_emmb15). Aloja un panel de seguridad escrito en Python que, entre otras cosas, captura tráfico de red. Un control de acceso deficiente lo hace vulnerable a un IDOR: cambiando el identificador numérico de la URL accedemos a la captura de otro usuario, y dentro del .pcap viajan unas credenciales FTP en texto plano. Con ellas entramos por SSH como nathan, y una Linux capability (cap_setuid+ep) sobre python3.8 nos lleva directo a root. Las IPs reales se omiten a propósito (<IP HTB>): reemplazalas por la de tu instancia.
Créditos: parte de la metodología está inspirada en el contenido educativo de S4vitar (video). Todos los créditos a él por el enfoque de enseñanza.
Técnicas utilizadas
| Fase | Técnica | Descripción |
|---|---|---|
| Reconocimiento | Escaneo de puertos (Nmap) | Identificación de servicios: FTP (21), SSH (22) y HTTP (80) |
| Enumeración | Análisis de la app web | El panel "Security Dashboard" y su captura de tráfico |
| Explotación | IDOR | Manipular el id de /data/<id> (ej. /data/0) para leer la captura de otro usuario |
| Post-explotación | Análisis de tráfico | Abrir el .pcap y seguir el stream FTP |
| Post-explotación | Credenciales en texto plano | Usuario y contraseña de nathan en el FTP sin cifrar |
| Acceso | Reutilización de credenciales (SSH) | Las mismas credenciales sirven para entrar por SSH |
| Escalada | Enumeración interna (getcap) | Capability cap_setuid+ep sobre /usr/bin/python3.8 |
| Escalada | Abuso de CAP_SETUID | os.setuid(0) en Python → shell como root |
Conceptos clave
| Concepto | Descripción |
|---|---|
| IDOR | La app expone una referencia directa a un objeto interno (un id) y no verifica si quien la pide está autorizado a verlo. Cambiando la referencia, accedés a recursos ajenos (CWE-639). |
| Broken Access Control (OWASP A01) | Categoría #1 del OWASP Top 10: las restricciones sobre lo que un usuario puede hacer no se aplican bien. El IDOR es un caso concreto (en APIs se le llama BOLA). |
| Archivos PCAP | Un .pcap guarda tráfico de red en crudo. Con Wireshark/tshark se inspecciona paquete a paquete y se reconstruyen sesiones completas, recuperando datos enviados por protocolos sin cifrar. |
| Protocolos inseguros | FTP, Telnet o HTTP básico transmiten credenciales sin cifrado: cualquiera con acceso al tráfico las lee directo. |
| Linux Capabilities (CAP_SETUID) | Linux divide los privilegios de root en unidades llamadas capabilities. CAP_SETUID deja a un proceso cambiar sus propios UIDs; si Python la tiene, un usuario sin privilegios puede poner su UID a 0 (root). |
Fase 1 · Reconocimiento
Arrancamos con un escaneo de todos los puertos para ver qué está expuesto:
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP HTB>

Con los puertos identificados (21/FTP, 22/SSH y 80/HTTP) lanzamos un escaneo de versiones y scripts por defecto:
nmap -sCV -p21,22,80 <IP HTB>

searchsploit openssh no da nada aprovechable (la versión está al día), así que accedemos directo a la web por la IP:
searchsploit openssh

Es un dashboard de seguridad y, curiosamente, ya aparecemos logueados como el usuario nathan. Toca recorrer sus pestañas para ver qué información expone.
En IP Config nos muestra la configuración de red del equipo que ejecuta el comando — o sea la de la máquina víctima (la IP no es la nuestra):

En Network Status vemos las conexiones tanto de Internet como de la propia máquina:

Y en Security Snapshot la carga tarda unos segundos (raro) y termina mostrando un resumen del tráfico:

El resumen trae número de paquetes totales, IP, TCP y UDP. Y podemos descargar la captura, que baja como 1.pcap:

Fase 2 · El IDOR en las capturas
Para leer un .pcap usamos tshark:
tshark -r 1.pcap

Salen muchísimos paquetes pero nada relevante. Si volvemos a la web y generamos otro Security Snapshot, los valores cambian cada vez, y el nombre del archivo va cambiando con ellos:

La clave está en la URL del dashboard: el número de la ruta coincide con el nombre del archivo que se descarga. Al generar otro snapshot nos carga, por ejemplo, 3.pcap:

Y en la barra de direcciones aparece exactamente ese identificador:

Si el recurso se referencia por un número en la URL, podemos cambiarlo a mano. Bajando el 3 a 1 navegamos a capturas anteriores:

¿Y si probamos el 0? Resulta que había una captura anterior a la nuestra. La descargamos para analizarla:

Esto es un IDOR de manual: la app no comprueba que la captura sea nuestra, así que accedemos a la de otro usuario solo cambiando el id.
Fase 3 · Credenciales en el tráfico FTP
Leemos el 0.pcap:
tshark -r 0.pcap

Esta vez sí hay algo: tráfico FTP, un protocolo sin cifrado. Si por ahí viajaron credenciales, estarán en texto plano. Filtramos por FTP:
tshark -r 0.pcap -Y "ftp"

Ahí están el usuario y la contraseña de nathan en claro. Como el puerto SSH está abierto, probamos a reutilizar esas credenciales:

Funciona: hay reutilización de credenciales. Con un pequeño tratamiento de la terminal ya podemos leer la user flag:

Fase 4 · Escalada de privilegios a root
Primero vemos en qué grupos estamos con id:
id

Nada especial. Enumeramos binarios SUID de root por si hay algo abusable:
find / -perm -4000 -user root 2>/dev/null | xargs ls -l

Salen muchas rutas pero nada útil. Antes de tirar de una enumeración completa, revisamos las capabilities del sistema:
getcap -r / 2>/dev/null

Aparece una capability rara sobre Python 3.8: si investigamos un poco, cap_setuid permite cambiar el SUID a cualquier valor, incluido el 0 de root:

Confirmamos que Python 3.8 está instalado y que cualquier usuario puede ejecutarlo:

Validamos ejecutando whoami a través de Python: nos devuelve nathan, como era de esperar:
python3.8 -c 'import os; os.system("whoami")'

Ahora aprovechamos la capability: si antes del comando hacemos os.setuid(0), el proceso pasa a ejecutarse como root:
python3.8 -c 'import os; os.setuid(0); os.system("whoami")'

En vez de un whoami, lanzamos directamente una bash como root:
python3.8 -c 'import os; os.setuid(0); os.system("bash")'

Con la shell privilegiada leemos la root flag y damos por comprometida la máquina. 🚩

Lecciones
- Verificá la autorización en cada objeto, no solo en el login. El IDOR salió de referenciar la captura por un id secuencial sin comprobar de quién es. Chequeá la propiedad del recurso en cada petición y, si podés, usá identificadores no predecibles.
- No transmitas credenciales por protocolos sin cifrar. El FTP en claro dejó el usuario y la contraseña a la vista de cualquiera que leyera el tráfico. FTPS/SFTP —o, en general, TLS— lo evitan.
- No reutilices contraseñas entre servicios. La misma credencial del FTP servía para SSH: un solo dato filtrado abrió la sesión completa.
- Cuidado con las Linux capabilities.
cap_setuid+epsobre un intérprete como Python equivale a regalar root. Otorgá capabilities al mínimo binario necesario, nunca a algo que ejecute código arbitrario.