
phpMyAdmin 5.2.3 - Alta - Remota - SQLi - ImportLdi TERMINATED BY leftover
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-importldi
Clase: SQLi Alcance: Remoto
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
ImportLdi.php construye LOAD DATA con FIELDS/LINES TERMINATED BY a partir de los POST ldi_terminated y ldi_new_line. Esas dos cadenas se concatenan en SQL entre comillas simples. ldi_enclosed y ldi_escaped pasan por escapeString. phpMyAdmin establece PMA_ENABLE_LDI en /import para que MYSQLI_OPT_LOCAL_INFILE esté activado.
Un usuario autenticado envía por POST format=ldi con una comilla en ldi_terminated. El LOAD DATA emitido contiene el POST sin procesar dentro de TERMINATED BY. Inyección SQL en la conexión del usuario, no en el usuario de control.
| ID | aún sin CVE |
| Clase | SQLi |
| Alcance | Remoto (inicio de sesión autenticado por cookie; importación de tabla, formato ldi) |
| CWE | CWE-89 |
| CVSS | Medio: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Producto | phpMyAdmin |
| Afectado | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Autenticación | inicio de sesión autenticado por cookie. Importación de tabla, formato ldi |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Un usuario autenticado de phpMyAdmin que puede abrir la importación de tabla puede inyectar SQL en LOAD DATA ... TERMINATED BY en su conexión MySQL.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en laboratorio o inferido |
|---|---|---|---|
Romper el literal FIELDS TERMINATED BY | POST index.php?route=/import format=ldi ldi_terminated con una comilla | Integridad de la sentencia que PMA construye | Probado en laboratorio. Cuadro SQL HTML: TERMINATED BY '',PMA-IMPORTLDI-WITNESS' |
Mantener ENCLOSED BY en banda | Mismo POST, comilla en ldi_enclosed | Control negativo | Probado en laboratorio. ENCLOSED BY está escapado |
| SQL adicional en la conexión del usuario (INTO OUTFILE / apilado si está permitido) | Mismo sink una vez cerrada la cadena | Integridad de la conexión del usuario | Inferido. El laboratorio se detiene en el delimitador roto. mysqli::query por defecto es de una sola sentencia |
| Lectura/escritura de archivos del lado de MySQL | Mismo LOAD DATA si la cuenta tiene FILE o LOCAL INFILE hacia el servidor web | Integridad de los archivos que mysqld puede tocar | Inferido. No concedido aquí. No afirmado |
Descartado en este laboratorio: acceso no autenticado, usuario de control / pmadb, LFI por include del SO, y lectura/escritura condicionada por FILE. El usuario autenticado ya tiene un cuadro SQL; este remanente es el delimitador sin escapar dentro de una sentencia que PMA construye para él.
Mismo pin: remanente de WebAuthn CustomServer.
Fijé phpMyAdmin RELEASE_5_2_3. Los plugins de importación que construyen LOAD DATA a mano son una auditoría de comillas. Dos de los cuatro campos de delimitador estaban escapados. Dos no lo estaban:
$sql .= ' FIELDS TERMINATED BY \'' . $ldi_terminated . '\'';
...
$sql .= ' LINES TERMINATED BY \'' . $ldi_new_line . '\'';
ldi_enclosed / ldi_escaped llaman a $dbi->escapeString. Common.php establece PMA_ENABLE_LDI en /import + format=ldi. Rutas GET|POST /import y GET|POST /table/import.
Caminos equivocados ya registrados: afirmar LFI sin una concesión FILE; tratar el cuadro SQL como el hallazgo (el remanente es el delimitador sin escapar que PMA concatena); afirmar usuario de control / pmadb; una reverse shell. Teatro.
python3 phpmyadmin-importldi-Abraxas-Labs.py
# or: cd lab && ./run.sh
Objetivo solo http://127.0.0.1:19290. Imágenes phpmyadmin:5.2.3 y mysql:8.0. Proyecto Compose phpmyadmin-importldi. El stack se desmonta tras la ejecución.
Inicio de sesión por cookie. POST /import con format=ldi y una comilla en ldi_terminated. Se emite LOAD DATA LOCAL INFILE ... INTO TABLE \ldi_target` FIELDS TERMINATED BY '',PMA-IMPORTLDI-WITNESS'. La misma comilla en ldi_enclosedse almacena como unENCLOSED BYescapado. El código fijado en la imagen 5.2.3 todavía tiene'.$ldi_terminated.'y$dbi->escapeString($ldi_enclosed)`.
SUCCESS phpmyadmin-importldi pin=RELEASE_5_2_3 how=live TERMINATED-BY-raw ENCLOSED-escaped PMA-IMPORTLDI-WITNESS
escapeString en ldi_terminated y ldi_new_line, igual que en enclosed y escaped. Conversión a int de skip_queries.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/Plugins/Import/ImportLdi.phpGNU Affero GPL v3.0. Ver LICENSE. Solo laboratorio en loopback. Sin garantía.