// 01
Resumen
Database es una máquina de dificultad media de la plataforma DockerLabs. Corre sobre Linux Ubuntu 22.04 (Jammy) y expone una aplicación web PHP con un formulario de login vulnerable a inyección SQL, un servicio SMB con recursos compartidos accesibles y acceso remoto via SSH.
El vector de ataque inicia con la explotación del login web mediante SQLMap,
lo que permite extraer credenciales de la base de datos MySQL. Posteriormente se accede al
servicio SMB con dichas credenciales, donde se obtiene un hash que al crackearse otorga
acceso SSH al usuario augustus. Desde ahí se realiza movimiento
lateral hacia dylan mediante una reverse shell en Java, y finalmente
se escala a root explotando el bit SUID del
binario /usr/bin/env.
| Fase | Técnica / Herramienta | Resultado |
|---|---|---|
| Reconocimiento | Nmap -sCV full scan | Puertos 22, 80, 139, 445 abiertos |
| Enumeración Web | Burp Suite + navegador | Request POST capturado |
| Explotación | SQLMap sobre request.txt | Credenciales: dylan / KJSDFG789FGSDF78 |
| Post-explotación | smbclient + CrackStation | Password de augustus: lovely |
| Acceso inicial | SSH + Java reverse shell | Shell como dylan |
| Privesc | SUID en /usr/bin/env | Shell como root |
// 02
Reconocimiento
El primer paso es desplegar la máquina vulnerable utilizando el script auto_deploy.sh que provee DockerLabs. Este script levanta un contenedor Docker a partir del archivo database.tar, asigna una IP automáticamente dentro de la red Docker (172.17.0.x) y mantiene la máquina activa hasta que se presiona Ctrl+C.
En una segunda terminal realizamos un escaneo exhaustivo de todos los puertos TCP de la máquina objetivo. Nmap descubre 4 puertos abiertos: SSH en el puerto 22, HTTP en el 80 con Apache 2.4.52 corriendo una aplicación PHP (título "Iniciar Sesión"), y Samba (SMB) en los puertos 139 y 445. El sistema operativo se identifica como Linux Ubuntu 22.04 Jammy.
La presencia simultánea de un login web y SMB expuesto es una señal de ataque interesante: si se obtienen credenciales por una vía, pueden reutilizarse en la otra.
// 03
Enumeración Web
Accedemos a http://172.17.0.2/ y encontramos una página de
login simple con campos User y Password. Se realizaron
intentos manuales de inyección SQL en los campos del formulario (payloads como
' OR 1=1--, ' OR '1'='1,
etc.) sin obtener resultado, ya que la aplicación no devuelve mensajes de error visibles
que permitan confirmar la vulnerabilidad de forma manual.
Para poder analizar la petición HTTP de forma estructurada y pasarla luego a SQLMap, interceptamos el tráfico con Burp Suite. Configuramos el proxy del navegador apuntando a Burp (127.0.0.1:8080), enviamos el formulario con las credenciales genéricas admin / admin y capturamos el request POST completo.
El request interceptado muestra que los parámetros enviados son
name y password via POST a
/index.php. Guardamos este request en un archivo
request.txt usando la opción "Save item" de Burp, lo que nos permitirá
pasárselo directamente a SQLMap.
// ¿POR QUÉ GUARDAR EL REQUEST?
SQLMap necesita conocer la estructura exacta de la petición HTTP para poder inyectar payloads en los parámetros correctos. Al pasarle el archivo con -r request.txt, no tenemos que especificar URL, método, cabeceras ni parámetros manualmente — SQLMap lo lee todo del archivo.
// 04
Explotación — SQL Injection
Ejecutamos SQLMap apuntando al archivo de request guardado. SQLMap detecta dos puntos de inyección: el parámetro name y el parámetro password, ambos de tipo Single quoted string en una petición POST. Seleccionamos el punto [1] — password para las inyecciones.
SQLMap confirma que el backend es MySQL ≥ 5.1 (MariaDB fork), que el servidor web corre Apache 2.4.52 sobre Ubuntu 22.04 Jammy.
Con la flag --dbs le indicamos a SQLMap que enumere todas las bases de datos disponibles en el servidor. Se obtienen 5 bases de datos: las 4 del sistema (information_schema, mysql, performance_schema, sys) y una personalizada: register. Esta última es la que contiene los datos de la aplicación.
Especificamos la base de datos register con la flag -D y le pedimos las tablas con --tables. SQLMap devuelve una única tabla: users. Esta tabla es la que almacena las credenciales del sistema.
Con la flag --dump extraemos el contenido completo de la tabla users. El resultado revela un único registro con las credenciales en texto plano. Intentamos conectarnos via SSH con estas credenciales pero el acceso fue denegado — el usuario dylan no tiene SSH habilitado directamente o la contraseña es incorrecta para SSH.
// 05
Enumeración SMB
Dado que SSH no funcionó con las credenciales de dylan, enumeramos el servicio SMB (Server Message Block) que Nmap detectó en los puertos 139 y 445. Usamos smbclient -L con la flag -N (null session, sin contraseña) para listar los recursos disponibles. Se identifican los shares estándar (print$, IPC$) y uno personalizado: shared.
Nos conectamos al recurso compartido shared autenticándonos
como el usuario dylan con la contraseña obtenida vía SQLMap. Dentro del
share encontramos un archivo de texto: augustus.txt. Lo descargamos
a nuestra máquina con el comando get de smbclient.
Al abrir augustus.txt encontramos una cadena de 32 caracteres hexadecimales: 061fba5bdfc076bb7362616668de87c8. La longitud y formato corresponden a un hash MD5. Para obtener el texto original usamos CrackStation, un servicio online que compara hashes contra enormes diccionarios precomputados (rainbow tables).
Introducimos el hash en CrackStation (crackstation.net). El servicio identifica el tipo como md5 y devuelve el resultado de forma inmediata: lovely. Esta es la contraseña del usuario augustus en el sistema.
// 06
Acceso Inicial — SSH
Con las credenciales obtenidas nos conectamos via SSH al usuario
augustus. El acceso es exitoso. Una vez dentro, ejecutamos
sudo -l para listar los comandos que augustus
puede ejecutar con privilegios elevados.
El sistema revela una entrada crítica: augustus puede ejecutar como el usuario dylan el binario /usr/bin/java sin necesidad de contraseña. Esto nos abre un vector de movimiento lateral hacia dylan.
// MOVIMIENTO LATERAL NECESARIO
Augustus puede ejecutar /usr/bin/java como dylan. Esto significa que si compilamos y ejecutamos código Java malicioso, ese proceso correrá con la identidad de dylan. El plan: crear una reverse shell en Java, compilarla en /tmp, y ejecutarla con sudo -u dylan.
// 07
Escalada de Privilegios — dylan
Usamos el generador online revshells.com para obtener el código fuente
de una reverse shell en Java. Configuramos como IP la dirección de nuestra máquina atacante
(172.17.0.1) y como puerto 9001.
El código generado crea una clase shell que al
ejecutarse abre una conexión TCP hacia nuestra máquina y lanza una bash interactiva.
Antes de ejecutar el payload, ponemos netcat a escuchar en el puerto 9001 para recibir la conexión entrante de la reverse shell. Es fundamental iniciar el listener antes de ejecutar el código Java.
Desde la sesión SSH de augustus, nos movemos al directorio
/tmp (escribible por todos los usuarios) y creamos el archivo
shell.java con el código de la reverse shell. Luego lo compilamos con
javac, lo que genera el bytecode shell.class.
Ejecutamos el payload Java usando el permiso sudo -u dylan.
La flag -cp /tmp indica el classpath (directorio donde
está shell.class) y shell
es el nombre de la clase a ejecutar. El proceso corre como dylan y la reverse shell
conecta con nuestro listener de netcat, otorgándonos una shell interactiva como dylan.
Ahora como dylan, buscamos binarios con el bit SUID activado usando find. Los binarios SUID se ejecutan con los permisos de su propietario (generalmente root) sin importar quién los invoque. Entre los resultados encontramos /usr/bin/env, que está listado en GTFOBins como explotable para escalar privilegios.
// 08
Root
Consultamos GTFOBins (gtfobins.github.io) para obtener el payload
correcto para /usr/bin/env con SUID. GTFOBins explica que
cuando env tiene el bit SUID activo, puede
spawner una shell heredando los privilegios elevados del propietario del binario (root),
siempre que se use la flag -p para evitar que el shell
descarte los privilegios efectivos.
Ejecutamos el comando de GTFOBins. La flag -p de
/bin/sh indica que se preserve el
effective UID (eUID = 0 = root) sin resetearlo al real UID del usuario que
lo invoca. El comando whoami confirma que somos root.
Máquina comprometida.
// 09
Referencia de Comandos
Descripción detallada de cada herramienta y comando utilizado en este writeup.
Escáner de redes y puertos. Permite descubrir qué puertos TCP/UDP están abiertos en un host y qué servicios (versión, OS, scripts) corren en ellos.
- -p- → escanea los 65535 puertos TCP
- -sS → SYN scan (sigiloso, no completa el handshake)
- -sC → ejecuta scripts NSE por defecto
- -sV → detecta versión de servicios
- -n → sin resolución DNS (más rápido)
- -Pn → skip host discovery (trata el host como activo)
- --min-rate=5000 → mínimo 5000 paquetes/segundo
- --open → muestra solo puertos abiertos
Herramienta automática de detección y explotación de inyecciones SQL. Soporta múltiples técnicas (boolean-based, time-based, UNION, etc.) y permite extraer el contenido completo de bases de datos.
- -r request.txt → lee la petición HTTP desde archivo
- --dbs → enumera todas las bases de datos
- -D <db> → selecciona una base de datos
- --tables → lista las tablas de la DB seleccionada
- -T <tabla> → selecciona una tabla
- --dump → extrae (vuelca) el contenido de la tabla
Cliente de línea de comandos para el protocolo SMB/CIFS. Permite listar recursos compartidos de red, conectarse a ellos, navegar directorios y transferir archivos, de forma similar a un cliente FTP.
- -L //IP/ → lista todos los shares disponibles
- -N → null session (sin autenticación)
- -U usuario → especifica el usuario a autenticar
- dir → (dentro del cliente) lista archivos
- get archivo → descarga un archivo al local
Utilidad de red multipropósito conocida como "la navaja suiza de TCP/IP". En pentesting se usa principalmente para establecer listeners que reciben conexiones de reverse shells.
- -l → modo escucha (listener)
- -v → verbose (muestra info de conexiones)
- -n → sin resolución DNS
- -p 9001 → puerto a escuchar
javac es el compilador de Java: transforma código fuente (.java) en bytecode (.class) ejecutable por la JVM. java ejecuta el bytecode compilado. Usados juntos permiten ejecutar un payload Java arbitrario.
- javac shell.java → compila y genera shell.class
- -cp /tmp → classpath: directorio donde buscar .class
- shell → nombre de la clase principal a ejecutar
- sudo -u dylan → ejecuta el proceso como dylan
El comando find busca archivos por criterios. Con -perm -4000 localiza todos los binarios con el bit SUID activo — archivos que se ejecutan con los permisos de su propietario, frecuentemente root.
- / → busca desde la raíz del sistema
- -perm -4000 → bit SUID activo (4 = SUID)
- 2>/dev/null → descarta errores de "permission denied"
env es un binario que ejecuta programas en un entorno modificado. Cuando tiene el bit SUID activo (propietario root), puede ser abusado para spawnear una shell con privilegios efectivos de root sin necesidad de contraseña.
- SUID → el proceso hereda el eUID del propietario (root)
- /bin/sh → shell a ejecutar
- -p → preserve privileges: no descarta el eUID=0
- GTFOBins → referencia: gtfobins.github.io/gtfobins/env/
sudo permite ejecutar comandos como otro usuario (por defecto root). -l lista qué comandos puede ejecutar el usuario actual. -u usuario especifica como qué usuario ejecutar — clave para el movimiento lateral de augustus a dylan.
- -l → lista permisos sudo del usuario actual
- -u dylan → ejecuta el siguiente comando como dylan
- (dylan) NOPASSWD: → sin contraseña requerida