phpMyAdmin 5.2.3 - Alta - Remota - SQLi - Identificadores no saneados en Designer JSON
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-designer-json-sqli
Write-up: https://abraxaslabs.tech/research/phpmyadmin-designer-json-sqli
Clase: SQLi Alcance: Remoto
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3, commit 962857e). El AJAX del Designer save_setting_value aplica json_encode al blob de ajustes y lo concatena en un UPDATE/INSERT entre comillas simples sobre el enlace del usuario de control. El nombre de usuario se escapa. El JSON no. json_encode no escapa una comilla simple.
Un usuario autenticado envía por POST a index.php?route=/database/designer con operation=save_setting_value y una comilla en value. queryAsControlUser ejecuta entonces esa cadena como el usuario de control de pma contra pma__designer_settings. Esa cuenta es el almacenamiento de configuración, no la caja SQL del usuario autenticado. phpMyAdmin 6.x envuelve este blob en quoteString en ControlUser. 5.2.3 todavía lo concatena en crudo.
Los CVE antiguos del designer (2016-6616, 2019-11768, 2019-18622) eran de nombre de usuario / nombre de base de datos. Este remanente es la columna JSON settings_data.
| ID | aún sin CVE |
| Clase | SQLi (usuario de control sobre pma__designer_settings) |
| Alcance | Remoto (login autenticado por cookie; Designer + pma__designer_settings habilitados) |
| CWE | CWE-89 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Producto | phpMyAdmin |
| Afectado | 5.2.3 tag RELEASE_5_2_3 (962857e) |
| Autenticación | Login autenticado por cookie. Designer + pma__designer_settings habilitados. |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1:19220 |
Un usuario autenticado de phpMyAdmin que pueda abrir el Designer puede inyectar SQL como el usuario de control sobre pma__designer_settings.
| Privilegio | Método / ruta | Probado en laboratorio o inferido |
|---|---|---|
| Romper la cadena UPDATE/INSERT del usuario de control (integridad del SQL de pmadb) | POST index.php?route=/database/designer operation=save_setting_value con una comilla en value | Probado en laboratorio. Log general: SET settings_data = '{"snap_line":"PMA-DESIGNER-JSON-SQLI-WITNESS'#" }' en crudo. quoteString ausente |
Truncar el propio settings_data para que deje de ser JSON (integridad de la propia fila) | Mismo POST; # comenta el resto de la sentencia | Probado en laboratorio. El blob de appuser contiene el testigo y no es JSON válido. El guardado limpio grid-ok desaparece |
| Sobrescribir las filas del designer de otros usuarios sin consultas apiladas (integridad de la fila de la víctima) | El mismo # comenta WHERE username = '...' | Probado en laboratorio. La semilla victim {"keep":"safe"} se convirtió en el blob testigo truncado |
| Sentencias adicionales como el usuario de control | Mismo sink si el enlace mysqli de control permite multi-query | Inferido. Por defecto mysqli::query es de una sola sentencia. No habilitado aquí |
Alcanzar otras tablas de pmadb (bookmarks, history, pma__userconfig) | Solo si son posibles las consultas apiladas o una ruptura de tipo escritura | Inferido. El usuario de control en este laboratorio solo tiene DML sobre phpmyadmin.* |
Cerrado en este laboratorio: acceso no autenticado, la caja SQL del appuser autenticado (solo appdb; appuser no tiene GRANT sobre phpmyadmin), shell del SO y consultas apiladas. La funcionalidad no hace nada si pmadb / los ajustes del designer están desactivados (eso es un FAIL, no este remanente).
Ocho búsquedas paralelas en el código fuente de RELEASE_5_2_3. saveSetting concatena json_encode dentro de '...'. El nombre de usuario pasa por escapeString. 6.x ya aplica quoteString a este blob. 5.2.3 no.
Errores de enfoque: inyectar en el nombre de usuario (está escapado); esperar un #1064 (el # comenta el resto, por lo que MySQL acepta el UPDATE truncado); tratar las consultas apiladas como probadas (el valor predeterminado de mysqli es una sola instrucción).
python3 phpmyadmin-designer-json-sqli-Abraxas-Labs.py
o
cd lab
./run.sh
Solo loopback: http://127.0.0.1:19220. Imágenes phpmyadmin:5.2.3 y mysql:8.0. Proyecto Compose phpmyadmin-designer-json-sqli. Testigo PMA-DESIGNER-JSON-SQLI-WITNESS.
SUCCESS phpmyadmin-designer-json-sqli version=5.2.3 how=live raw-concat=yes truncated=true sql-error=false quoteString=no PMA-DESIGNER-JSON-SQLI-WITNESS
quoteString(..., ControlUser) / escapeString sobre el blob JSON, igual que RecentFavoriteTable::saveToDb() y phpMyAdmin 6.x en esta columna. No coloque la salida de json_encode dentro de un literal SQL entre comillas simples.
962857e)libraries/classes/Database/Designer/Common.php saveSettingControllers/Database/DesignerController.php POST operation=save_setting_valueGET|POST /database/designerGNU Affero GPL v3.0. Consulte LICENSE. Solo para laboratorio de loopback. Sin garantía.