Cap
Executive summary — Cap is a very elegant Easy Linux box with no public exploit involved: everything rests on design flaws. An IDOR in a «security» dashboard lets us download another session's network capture (.pcap), where cleartext FTP credentials travel; with them we log into FTP and SSH (password reuse), and the final escalation abuses a Linux capability (
cap_setuid) granted topython3.8to become root without touchingsudoor SUID. An IDOR → PCAP → FTP/SSH → capabilities → root path.
| Platform | Hack The Box |
| Operating system | Linux |
| Difficulty | Easy |
| Status | Retired |
| Target IP | 10.129.17.19 |
Attack map
[80] security dashboard · /capture → /data/1
│ IDOR: change the ID → /data/0 downloads 0.pcap (another session capture)
▼
[PCAP] Wireshark → cleartext FTP traffic → nathan:Buck3tH4TF0RM3!
▼
[FTP] login nathan → user.txt
▼
[SSH] nathan → interactive shell
│ find -perm -4000 → nothing useful · getcap → /usr/bin/python3.8 = cap_setuid+ep
▼
[ROOT] python3.8 -c "os.setuid(0); os.system('/bin/bash')"
1. Reconnaissance
As always, we start with a full port scan instead of trusting nmap's default top-1000: on HTB boxes you never know which «odd» service is hiding on a high port.
nmap -p- --open -n -T5 -v 10.129.17.19
Why these flags:
-p-→ scans all 65535 ports, not just the most common ones.--open→ only shows ports that answer as open, keeping the output clean.-n→ no DNS resolution, faster scan.-T5→ very aggressive timing template (lab network, no IDS to worry about).-v→ verbose mode, so ports show up as they're confirmed.
21/tcp open ftp
22/tcp open ssh
80/tcp open http
Analysis: three very classic services —FTP, SSH and HTTP—. The «web with something interesting + FTP with credentials + SSH to get in» pattern is common on Easy boxes, so we start with the web.
Resumen ejecutivo — Cap es un Linux Easy muy elegante en el que no hay un exploit público de por medio: todo se apoya en fallos de diseño. Un IDOR en un dashboard de «seguridad» permite descargar la captura de red (.pcap) de otra sesión, donde viajan credenciales FTP en texto claro; con ellas se entra por FTP y por SSH (reutilización de contraseña), y la escalada final abusa de una Linux capability (
cap_setuid) concedida apython3.8para convertirse en root sin pasar porsudoni por SUID. Recorrido IDOR → PCAP → FTP/SSH → capabilities → root.
| Plataforma | Hack The Box |
| Sistema operativo | Linux |
| Dificultad | Easy |
| Estado | Retired |
| IP objetivo | 10.129.17.19 |
Mapa del ataque
[80] dashboard de seguridad · /capture → /data/1
│ IDOR: cambiar el ID → /data/0 descarga 0.pcap (captura de otra sesión)
▼
[PCAP] Wireshark → tráfico FTP en claro → nathan:Buck3tH4TF0RM3!
▼
[FTP] login nathan → user.txt
▼
[SSH] nathan → shell interactiva
│ find -perm -4000 → nada útil · getcap → /usr/bin/python3.8 = cap_setuid+ep
▼
[ROOT] python3.8 -c "os.setuid(0); os.system('/bin/bash')"
1. Reconocimiento
Empezamos, como siempre, con un escaneo completo de puertos en lugar de fiarnos del top-1000 de nmap: en máquinas de HTB nunca se sabe qué servicio «raro» esconden en un puerto alto.
nmap -p- --open -n -T5 -v 10.129.17.19
Por qué estas flags:
-p-→ escanea los 65535 puertos, no solo los más comunes.--open→ muestra solo los puertos que responden abiertos, para no ensuciar la salida.-n→ sin resolución DNS, escaneo más rápido.-T5→ plantilla de tiempo muy agresiva (red de laboratorio, sin miedo a IDS).-v→ modo verbose, para ver los puertos según se van confirmando.
21/tcp open ftp
22/tcp open ssh
80/tcp open http
Análisis: tres servicios muy clásicos —FTP, SSH y HTTP—. El patrón «web con algo interesante + FTP con credenciales + SSH para entrar» es habitual en máquinas Easy, así que empezamos por la web.
2. Web enumeration: the dashboard
We browse to http://10.129.17.19 and find a security dashboard: an application supposedly built to capture and analyse network traffic. Poking at its routes by hand turns up one that stands out:
/capture
Visiting http://10.129.17.19/capture makes the server generate a new network capture (a .pcap) and redirects us to:
http://10.129.17.19/capture → /data/1
What's happening: the app numbers each capture and serves it at
/data/<id>. Indexing resources by a sequential, predictable number, without checking that the capture actually belongs to whoever requests it, is the exact recipe for an IDOR (Insecure Direct Object Reference).
3. Key vulnerability — IDOR
If the server never validates that capture 1 is «ours», nothing stops us from requesting a different number. We try the most obvious one, 0 —usually the oldest ID, often generated by an automated process or by the admin—:
http://10.129.17.19/data/0
Result: we download
0.pcap, a network capture that isn't ours. The flaw isn't technical or sophisticated: it's a total absence of object-level authorisation. Authentication (if there even is any) doesn't matter if anyone can request anyone else's resource by changing a number in the URL.
4. PCAP analysis → FTP credentials
We open the downloaded capture in Wireshark and filter for the protocol we care about most when credentials are involved:
wireshark 0.pcap # display filter: ftp
Among the filtered packets, a full FTP login shows up in plain text:
USER nathan
PASS Buck3tH4TF0RM3!
Why it works: plain FTP (not FTPS) encrypts neither the control channel nor the data: username and password travel in the clear inside the TCP packets. Anyone who captures that traffic —or downloads the capture, as here— gets the credentials without breaking anything.
5. Initial access — FTP
We try the recovered credentials directly against the service they came from:
ftp 10.129.17.19
# Username: nathan
# Password: Buck3tH4TF0RM3!
Once logged in, we switch to binary mode (to avoid corrupting the file) and grab the user flag:
binary
get user.txt
cat user.txt
6. Interactive access — SSH
FTP gets us the flag, but it's a session limited to file transfer: no good for enumerating the system or escalating privileges. We try the same username/password pair against SSH, betting that nathan reuses the same password across services:
ssh nathan@10.129.17.19
# password: Buck3tH4TF0RM3!
Credential reuse: it works, giving us a full interactive shell as
nathan—the real starting point for the escalation phase.
7. Enumeration for privilege escalation
Before looking at anything exotic, we check the classic first: binaries with the SUID bit set, which run with their owner's privileges instead of the invoking user's:
find / -perm -4000 -type f 2>/dev/null
Nothing out of the ordinary: the SUID binaries are the usual ones shipped with any distribution (passwd, sudo, etc.), no exploitable candidate. We move on to the modern equivalent of SUID: Linux capabilities.
getcap -r / 2>/dev/null
/usr/bin/python3.8 = cap_setuid+ep
There it is: unlike SUID (which affects the whole binary), here an entire general-purpose interpreter,
python3.8, has been granted a very powerful capability.
8. Vulnerability — Linux Capabilities
Capabilities are the Linux kernel's way of slicing up root's privileges into smaller pieces and handing a specific one to a specific binary, instead of giving it all of root's power (as the classic SUID bit does) or none at all. In theory this is a more secure model than SUID… if configured carefully.
The problem with
cap_setuidon an interpreter: this capability lets the process change its own UID, including to another user's or to root's (UID 0). Granting it to a closed, single-purpose binary is reasonably safe; granting it to a general-purpose interpreter like Python hands over the keys to the house —from Python you can run any code, including code that becomes root.
9. Escalating to root
We don't need to start as root or go through sudo: we simply ask the interpreter (which already holds the privilege) to change its own UID to 0 and spawn a shell:
/usr/bin/python3.8 -c 'import os; os.setuid(0); os.system("/bin/bash")'
What each line does:
os.setuid(0)→ thanks tocap_setuid, the Python process changes its effective UID to0(root).os.system("/bin/bash")→ spawns a shell that inherits that already-elevated UID.
id → uid=0(root)
10. Root flag
cat /root/root.txt
System fully compromised. 🏴☠️
Vulnerability summary
| Phase | Component | Vulnerability | Impact |
|---|---|---|---|
| Info leak | Web app (/data/<id>) | IDOR: no object-level access control on captures indexed by ID | Download of other sessions' network captures |
| Info leak | Network capture (PCAP) | Cleartext FTP traffic inside the leaked capture | Recovery of valid credentials (nathan) |
| Foothold | FTP / SSH | Same password reused across services, with no extra control | FTP session (user.txt) and interactive SSH shell as nathan |
| PrivEsc | python3.8 | cap_setuid capability granted to a general-purpose interpreter | Execution as root |
Lessons learned
- IDOR: referencing objects by a sequential, predictable ID without checking resource ownership exposes other users' data. Authorise every access, don't just authenticate.
- FTP is cleartext: never transmit or store credentials over FTP; use FTPS or SFTP.
- Network captures are gold for an attacker: an accessible
.pcapcan hold cleartext secrets captured from legitimate sessions. - Don't reuse passwords across services: a credential leaked on one protocol compromises every service that shares it.
- Audit Linux capabilities, not just SUID:
cap_setuid(orcap_setgid,cap_dac_override…) on a general-purpose interpreter is equivalent to handing out root access. Review withgetcap -r /as thoroughly as you'd review SUID binaries.
2. Enumeración web: el dashboard
Navegamos a http://10.129.17.19 y nos encontramos con un dashboard de seguridad: una aplicación pensada, en teoría, para capturar y analizar tráfico de red. Explorando sus rutas a mano damos con una que llama la atención:
/capture
Al visitar http://10.129.17.19/capture, el servidor genera una nueva captura de red (un .pcap) y nos redirige a:
http://10.129.17.19/capture → /data/1
Qué está pasando: la aplicación numera cada captura y la sirve en
/data/<id>. Indexar recursos por un número secuencial y predecible, sin comprobar que la captura pertenece a quien la pide, es la receta exacta de un IDOR (Insecure Direct Object Reference).
3. Vulnerabilidad clave — IDOR
Si el servidor no valida que la captura 1 sea «nuestra», nada nos impide pedir otro número. Probamos el más obvio, el 0 —normalmente el ID más antiguo, a menudo generado por un proceso automático o por el administrador—:
http://10.129.17.19/data/0
Resultado: descargamos
0.pcap, una captura de red que no es nuestra. El fallo no es técnico ni sofisticado: es la ausencia total de un control de autorización a nivel de objeto. La autenticación (si la hay) no importa si cualquiera puede pedir el recurso de cualquier otro cambiando un número en la URL.
4. Análisis del PCAP → credenciales FTP
Abrimos la captura descargada en Wireshark y filtramos por el protocolo que más nos interesa cuando hay credenciales de por medio:
wireshark 0.pcap # filtro de visualización: ftp
Entre los paquetes filtrados aparece, en texto plano, el login completo de una sesión FTP:
USER nathan
PASS Buck3tH4TF0RM3!
Por qué funciona: FTP (el protocolo «clásico», no FTPS) no cifra ni el canal de control ni los datos: usuario y contraseña viajan en claro dentro de los paquetes TCP. Cualquiera que capture ese tráfico —o descargue la captura, como en este caso— obtiene las credenciales sin necesidad de romper nada.
5. Acceso inicial — FTP
Probamos las credenciales encontradas directamente contra el servicio del que salieron:
ftp 10.129.17.19
# Username: nathan
# Password: Buck3tH4TF0RM3!
Con sesión abierta, cambiamos a modo binario (para no corromper el archivo) y descargamos la flag de usuario:
binary
get user.txt
cat user.txt
6. Acceso interactivo — SSH
FTP nos da la flag, pero es una sesión limitada a transferencia de ficheros: no sirve para enumerar el sistema ni para escalar privilegios. Probamos la misma pareja usuario/contraseña contra SSH, asumiendo que nathan reutiliza su contraseña entre servicios:
ssh nathan@10.129.17.19
# contraseña: Buck3tH4TF0RM3!
Reutilización de credenciales: funciona, y así conseguimos una shell interactiva completa como
nathan, el punto de partida real para la fase de escalada.
7. Enumeración para escalada de privilegios
Antes de mirar nada exótico, comprobamos el clásico: binarios con el bit SUID activo, que se ejecutan con los privilegios de su propietario en lugar de los del usuario que los lanza:
find / -perm -4000 -type f 2>/dev/null
Nada fuera de lo normal: los binarios SUID del sistema son los habituales de cualquier distribución (passwd, sudo, etc.), sin ningún candidato explotable. Pasamos al equivalente moderno del SUID: las Linux capabilities.
getcap -r / 2>/dev/null
/usr/bin/python3.8 = cap_setuid+ep
Ahí está: a diferencia del SUID (que afecta al binario entero), aquí un intérprete completo como
python3.8tiene concedida una capability muy potente.
8. Vulnerabilidad — Linux Capabilities
Las capabilities son la forma que tiene el kernel de Linux de trocear los privilegios de root en piezas más pequeñas y otorgárselas a un binario concreto, en vez de darle todo el poder de root (como hace el bit SUID clásico) o nada. En teoría es un modelo más seguro que SUID… si se configura con cuidado.
El problema con
cap_setuidsobre un intérprete: esta capability permite al proceso cambiar su propio UID, incluido el de otro usuario o el de root (UID 0). Concedérsela a un binario cerrado y de propósito único es razonablemente seguro; concedérsela a un intérprete de propósito general como Python es entregar las llaves de la casa —desde Python se puede ejecutar cualquier código, incluido el que se convierte en root.
9. Escalada a root
No hace falta ser root de partida ni pasar por sudo: le pedimos directamente al intérprete (que ya tiene el privilegio) que cambie su propio UID a 0 y lance una shell:
/usr/bin/python3.8 -c 'import os; os.setuid(0); os.system("/bin/bash")'
Qué hace cada línea:
os.setuid(0)→ gracias acap_setuid, el proceso Python cambia su UID efectivo a0(root).os.system("/bin/bash")→ lanza una shell que hereda ese UID ya elevado.
id → uid=0(root)
10. Root flag
cat /root/root.txt
Sistema comprometido por completo. 🏴☠️
Resumen de vulnerabilidades
| Fase | Componente | Vulnerabilidad | Impacto |
|---|---|---|---|
| Info leak | App web (/data/<id>) | IDOR: sin control de acceso a nivel de objeto sobre las capturas indexadas por ID | Descarga de capturas de red de otras sesiones |
| Info leak | Captura de red (PCAP) | Tráfico FTP en texto claro dentro de la captura filtrada | Recuperación de credenciales válidas (nathan) |
| Foothold | FTP / SSH | Reutilización de la misma contraseña entre servicios, sin control adicional | Sesión FTP (user.txt) y shell interactiva SSH como nathan |
| PrivEsc | python3.8 | Capability cap_setuid concedida a un intérprete de propósito general | Ejecución como root |
Lecciones aprendidas
- IDOR: referenciar objetos por un ID secuencial y predecible, sin comprobar la propiedad del recurso, expone datos de otros usuarios. Autoriza cada acceso, no solo autentica.
- FTP va en claro: nunca transmitas ni almacenes credenciales sobre FTP; usa FTPS o SFTP.
- Las capturas de red son oro para un atacante: un
.pcapaccesible puede contener secretos en claro capturados de sesiones legítimas. - No reutilices contraseñas entre servicios: una credencial filtrada en un protocolo compromete todos los que la comparten.
- Audita las Linux capabilities, no solo el SUID:
cap_setuid(ocap_setgid,cap_dac_override…) sobre un intérprete de propósito general equivale a darle acceso root. Revisa congetcap -r /tan a fondo como revisarías los SUID.