// 01
Resumen
Trust es una máquina de dificultad muy fácil de la plataforma DockerLabs, publicada el 02/04/2024. Corre sobre Linux Debian y expone únicamente dos servicios: SSH (puerto 22) y un servidor web HTTP (puerto 80) con Apache 2.4.57.
El vector de ataque arranca con la enumeración del servidor web mediante Gobuster,
que descubre un archivo secret.php con el mensaje
"Hola Mario" — lo que revela directamente el nombre de usuario del sistema.
Con ese dato se ejecuta un ataque de diccionario sobre SSH usando Hydra
con el wordlist rockyou.txt, obteniendo la contraseña
chocolate. Una vez dentro como mario,
la escalada a root se logra aprovechando que el usuario puede
ejecutar vim con sudo sin restricciones,
escapando a una shell privilegiada con un solo comando.
| Fase | Técnica / Herramienta | Resultado |
|---|---|---|
| Despliegue | auto_deploy.sh + ping | Máquina activa en 172.18.0.2 |
| Reconocimiento | Nmap -sSCV full scan + xsltproc | Puertos 22 y 80 abiertos; Apache 2.4.57 |
| Enum. Web | Gobuster dir + extensiones php,html | secret.php descubierto (status 200) |
| OSINT pasivo | Lectura de secret.php en navegador | Usuario: mario |
| Acceso inicial | Hydra SSH brute force + rockyou.txt | Contraseña: chocolate |
| Acceso inicial | SSH mario@172.18.0.2 | Shell como mario |
| Enum. post-acceso | sudo -l + find SUID | vim ejecutable como root via sudo |
| Privesc | sudo vim -c ':!/bin/bash' | Shell como root ✓ |
// 02
Reconocimiento
El primer paso es desplegar la máquina vulnerable. DockerLabs proporciona el script auto_deploy.sh que construye el contenedor Docker a partir de trust.tar, asigna una IP dentro de la red interna Docker (172.18.0.x) y mantiene la máquina activa hasta que se presiona Ctrl+C. Se requiere sudo porque Docker necesita privilegios para gestionar redes e imágenes.
Antes de cualquier escaneo, verificamos que la máquina está activa y responde a tráfico ICMP. La flag -c 3 limita el envío a 3 paquetes para no saturar la red. Un TTL=64 en la respuesta confirma que el sistema operativo objetivo es Linux, ya que Windows devuelve TTL=128 por defecto. Este dato es útil para orientar el reconocimiento posterior.
Con conectividad confirmada, lanzamos un escaneo exhaustivo con Nmap. La combinación de flags -p- escanea los 65535 puertos TCP, -sSCV realiza un SYN scan sigiloso, detecta versiones de servicio y ejecuta los scripts NSE por defecto. Las flags -n -Pn desactivan la resolución DNS y el ping previo (útil en entornos Docker donde el ICMP puede estar filtrado). --min-rate=5000 acelera el escaneo enviando al menos 5000 paquetes por segundo. El resultado se exporta a XML con -oX para procesarlo después con xsltproc.
// HALLAZGOS CLAVE
Solo 2 puertos abiertos: 22 (SSH) con OpenSSH 9.2p1 Debian y 80 (HTTP) con Apache 2.4.57 Debian. Sin FTP, sin SMB. La superficie de ataque es mínima — todo el reconocimiento se centrará en el servidor web para obtener un vector de entrada hacia SSH.
Convertimos el XML de Nmap a HTML para tener una vista más cómoda y legible del escaneo. xsltproc aplica la hoja de estilos XSL oficial de Nmap sobre el XML generado y produce un informe HTML navegable con tabla de puertos, versiones y scripts NSE.
// 03
Enumeración Web
El puerto 80 muestra la página por defecto de Apache ("It works"), que no contiene información útil. El siguiente paso es aplicar fuzzing de directorios y archivos con Gobuster. A diferencia de wfuzz, Gobuster está escrito en Go y es notablemente más rápido en targets locales. Usamos el wordlist DirBuster-2007 directory-list-lowercase-2.3-medium.txt de SecLists (uno de los más completos para CTFs), y añadimos las extensiones html, php, sh, py para descubrir no solo directorios sino también archivos con esas extensiones.
Gobuster revela un archivo secret.php con status 200.
Al navegar a http://172.18.0.2/secret.php
en el navegador, encontramos el mensaje:
El mensaje nos saluda por nombre: Mario. Esta es la pista de OSINT pasivo de la máquina — el desarrollador dejó expuesto el nombre de un usuario real del sistema. En CTFs de nivel fácil, este tipo de "descuidos" son intencionados y forman parte del vector de ataque. Ya tenemos el primer factor de las credenciales SSH: usuario = mario.
// NOTA: SURFACE DE ATAQUE REDUCIDA
En esta máquina no hay FTP anónimo ni directorios de backup como en Obsession. El único dato que necesitamos extraer del servidor web es el nombre de usuario, y lo obtenemos directamente de secret.php. Todo lo demás lo resuelve Hydra contra SSH.
// 04
Acceso Inicial
Con el usuario mario confirmado, lanzamos Hydra para realizar un ataque de diccionario contra el servicio SSH del puerto 22. Usamos rockyou.txt, el wordlist de contraseñas más utilizado en CTFs (14.3 millones de contraseñas reales filtradas del breche RockYou 2009). La flag -f detiene Hydra en cuanto encuentra la primera combinación válida. Con -t 20 lanzamos 20 hilos en paralelo y -V muestra cada intento en pantalla para monitorear el progreso.
Con las credenciales obtenidas, nos conectamos por SSH. Si el sistema ya almacenó
una clave del host anterior para esta IP (por ejemplo de otra máquina Docker), SSH
bloqueará la conexión por discrepancia de fingerprint. En ese caso, se elimina la
entrada antigua con ssh-keygen -R 172.18.0.2
y se reconecta. Al conectar por primera vez, SSH pedirá confirmación para almacenar
el nuevo fingerprint — respondemos yes.
// SHELL OBTENIDA
Acceso inicial conseguido como mario. Ahora comenzamos la fase de enumeración post-acceso para buscar vectores de escalada de privilegios. Objetivo: llegar a root.
// 05
Escalada de Privilegios
Los dos comandos más importantes al obtener acceso a un sistema Linux son sudo -l y la búsqueda de binarios con bit SUID. El primero lista qué comandos puede ejecutar el usuario actual con privilegios de otro usuario (normalmente root) mediante sudo. El segundo busca binarios con el bit SUID activo que se ejecuten con los permisos del propietario (root), y que podamos abusar para escalar privilegios.
// ANÁLISIS DE VECTORES
Los binarios SUID encontrados (su, mount, passwd, sudo...) son todos parte
del sistema base de Debian y no tienen exploits directos aplicables aquí. El vector real y
limpio es sudo vim: mario puede ejecutar vim como root sin restricciones
((ALL) /usr/bin/vim), y vim permite escapar a una shell interactiva mediante
su funcionalidad de ejecución de comandos.
Vim tiene una funcionalidad de comandos Ex que permite ejecutar comandos de shell directamente desde dentro del editor. La flag -c ejecuta un comando Ex al arrancar Vim, antes de mostrar ningún buffer. El comando :!/bin/bash invoca una shell desde Vim. Como Vim se ejecuta con sudo, la shell heredada es de root. No es necesario abrir ningún archivo ni editar nada — el exploit ocurre en el arranque.
// 06
Referencia de Comandos
Escáner de puertos y servicios. El más utilizado en reconocimiento activo. Combina detección de versiones, scripts NSE y escaneo sigiloso SYN.
-p-→ todos los puertos (1–65535)-sS→ SYN scan (sigiloso, no completa handshake)-sC→ scripts NSE por defecto-sV→ detección de versiones-n→ sin resolución DNS-Pn→ sin ping previo--min-rate=5000→ velocidad mínima de paquetes-oX→ exportar a XML
Fuzzer de directorios y archivos web escrito en Go. Más rápido que DirBuster en la mayoría de escenarios. Ideal para descubrir rutas ocultas en servidores web.
dir→ modo de enumeración de directorios-u→ URL objetivo-w→ wordlist a usar-x→ extensiones a probar (php,html,sh...)-t→ número de hilos (default: 10)-o→ guardar output a archivo
Herramienta de fuerza bruta para múltiples protocolos de red. Soporta SSH, FTP, HTTP, SMB, RDP, y muchos más. Paraleliza los intentos con múltiples hilos.
-l→ usuario único-L→ lista de usuarios-p→ contraseña única-P→ wordlist de contraseñas-f→ parar al encontrar primera credencial válida-t N→ N hilos paralelos-V→ verbose (muestra cada intento)
sudo -l lista los comandos que puede ejecutar el usuario actual con privilegios elevados. GTFOBins cataloga cómo abusar de binarios legítimos para escalar privilegios.
sudo -l→ lista de permisos sudo del usuariosudo vim -c ':!/bin/bash'→ shell root via vimsudo vim -c ':py import os; os.execl("/bin/bash"...)'→ via Pythonsudo find . -exec /bin/bash \;→ via findsudo python3 -c 'import os; os.system("/bin/bash")'→ via Python
// 07
Glosario
dir (directorios), dns (subdominios), vhost (virtual hosts) y s3 (buckets). En el modo dir, Gobuster prueba cada entrada del wordlist como ruta en el servidor web, opcionalmente añadiendo extensiones de archivo, y reporta las que devuelven un código de estado HTTP no bloqueado (normalmente 200, 301, 302)./admin), archivos de configuración (config.php), backups (backup.zip), páginas de desarrollo (secret.php), etc. Las wordlists más usadas en CTFs son las de SecLists (DirBuster, Discovery, common.txt)./etc/sudoers. El comando sudo -l lista todos los permisos del usuario actual sin necesidad de ser root. Una regla como (ALL) /usr/bin/vim significa que el usuario puede ejecutar vim como cualquier usuario del sistema, incluyendo root. Si un binario con acceso sudo permite ejecutar comandos de shell (como vim, python, find, less...), se convierte en un vector de escalada de privilegios catalogado en GTFOBins.:!/bin/bash para obtener una shell interactiva como root, aprovechando que vim puede invocar comandos de shell externos desde su modo de comandos Ex.:! permite ejecutar comandos de shell externos. Por ejemplo, :!/bin/bash abre una bash interactiva desde dentro de Vim. La flag -c de Vim ejecuta un comando Ex directamente al arrancar, antes de mostrar ningún buffer de edición. Cuando Vim se lanza con sudo, la shell invocada hereda los privilegios de root. Este comportamiento está documentado en GTFOBins bajo la sección "Shell" de vim con la entrada "Sudo".secret.php en un navegador, una acción que cualquier usuario haría al explorar un sitio web. Este tipo de "fuga de información" es un misconfiguration real: nunca se deben exponer nombres de usuarios, rutas internas o información de sistema en páginas web accesibles públicamente.~/.ssh/known_hosts. Si la clave del servidor cambia (por ejemplo, al recrear un contenedor Docker con la misma IP), SSH bloquea la conexión por seguridad. En entornos CTF esto ocurre con frecuencia — la solución es eliminar la entrada antigua con ssh-keygen -R <IP> y reconectar. En redes reales, un cambio de clave inesperado podría indicar un ataque real y nunca debería ignorarse sin investigar.