Saltar al contenido
cd ..
HTBEXP-0005
RESUELTA

Cap

Linux Fácil 13 min de lectura
IDORPCAPLinux Capabilities
EMemmb15ago 2026

Writeup en video

Recorrido completo de Cap: del reconocimiento a la raíz, paso a paso.

Cap — HackTheBox

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

FaseTécnicaDescripción
ReconocimientoEscaneo de puertos (Nmap)Identificación de servicios: FTP (21), SSH (22) y HTTP (80)
EnumeraciónAnálisis de la app webEl panel "Security Dashboard" y su captura de tráfico
ExplotaciónIDORManipular el id de /data/<id> (ej. /data/0) para leer la captura de otro usuario
Post-explotaciónAnálisis de tráficoAbrir el .pcap y seguir el stream FTP
Post-explotaciónCredenciales en texto planoUsuario y contraseña de nathan en el FTP sin cifrar
AccesoReutilización de credenciales (SSH)Las mismas credenciales sirven para entrar por SSH
EscaladaEnumeración interna (getcap)Capability cap_setuid+ep sobre /usr/bin/python3.8
EscaladaAbuso de CAP_SETUIDos.setuid(0) en Python → shell como root

Conceptos clave

ConceptoDescripción
IDORLa 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 PCAPUn .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 insegurosFTP, 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>

Escaneo de todos los puertos

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>

Escaneo de servicios y versiones

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

La web servida por la IP

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):

IP Config de la máquina víctima

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

Network Status

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

Security Snapshot

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

Descargando 1.pcap

Fase 2 · El IDOR en las capturas

Para leer un .pcap usamos tshark:

tshark -r 1.pcap

Leyendo 1.pcap con tshark

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:

Los valores cambian en cada snapshot

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:

Nuevo snapshot: 3.pcap

Y en la barra de direcciones aparece exactamente ese identificador:

El id en la URL

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:

Cambiando el id de 3 a 1

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

Existe un 0.pcap

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

Leyendo 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"

Credenciales FTP en texto plano

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

Login por SSH como nathan

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

User flag

Fase 4 · Escalada de privilegios a root

Primero vemos en qué grupos estamos con id:

id

Grupos del usuario nathan

Nada especial. Enumeramos binarios SUID de root por si hay algo abusable:

find / -perm -4000 -user root 2>/dev/null | xargs ls -l

Binarios SUID de root

Salen muchas rutas pero nada útil. Antes de tirar de una enumeración completa, revisamos las capabilities del sistema:

getcap -r / 2>/dev/null

Capabilities del sistema

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:

La capability cap_setuid sobre python3.8

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

python3.8 es ejecutable

Validamos ejecutando whoami a través de Python: nos devuelve nathan, como era de esperar:

python3.8 -c 'import os; os.system("whoami")'

whoami vía Python → nathan

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")'

whoami tras setuid(0) → root

En vez de un whoami, lanzamos directamente una bash como root:

python3.8 -c 'import os; os.setuid(0); os.system("bash")'

Shell de root

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

Root flag

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+ep sobre un intérprete como Python equivale a regalar root. Otorgá capabilities al mínimo binario necesario, nunca a algo que ejecute código arbitrario.