
phpMyAdmin 5.2.3 - Alta - Remota - residual - setup/validate aún accesible
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-setup-validate
Clase: SSRF Alcance: Remoto
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3, commit 962857e). setup/index.php muere cuando config.inc.php está presente. setup/validate.php no. Todavía se carga bajo $isMinimumCommon, toma un token CSRF de la página de inicio de sesión pública y llama a Validator::testDBConnection -> mysqli_connect al host, puerto, usuario y contraseña en el campo JSON values.
Un cliente no autenticado hace GET a / para obtener una cookie de sesión y un token, luego hace POST a setup/validate.php id=Server con Servers/1/host y Servers/1/port de su elección. El host de phpMyAdmin abre un handshake TCP de MySQL a esa dirección. Eso es SSRF sobre el protocolo MySQL: 3306 interno, credential stuffing contra un servidor interno, un oráculo de puertos a partir del timing y los errores de mysqli. No es SSRF de metadatos HTTP a menos que algo en ese puerto hable MySQL. hide_db también interpola una regex de usuario en preg_match. No ejecuté esa ruta de ReDoS en este laboratorio.
La imagen oficial phpmyadmin:5.2.3 elimina setup/. Este remanente solo aplica cuando ese directorio sigue en la raíz web, que es el remanente común tras una instalación. El laboratorio restaura setup/ desde el tarball 5.2.3 para que el pin coincida con RELEASE_5_2_3.
PMASA-2016-44 / CVE-2016-6621 cubrió algo de SSRF en setup. La comprobación de "deshabilitar setup cuando existe config" nunca se aplicó a validate.php / config.php.
| ID | sin CVE aún |
| Clase | SSRF (protocolo MySQL) |
| Alcance | Remoto (no autenticado si setup/ sigue siendo accesible por web) |
| CWE | CWE-918 |
| CVSS | Alto: 7.2 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N |
| Producto | phpMyAdmin |
| Afectado | 5.2.3 tag RELEASE_5_2_3 (962857e) con setup/ todavía en el docroot |
| Auth | No autenticado. Token CSRF de la página de inicio de sesión pública. Sin login de MySQL. |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1:19230 |
Cualquiera que pueda alcanzar un árbol setup/ remanente puede hacer que el host de phpMyAdmin abra una conexión TCP de protocolo MySQL a un host y puerto que elija.
| Privilegio | Método / ruta | Probado en laboratorio o inferido |
|---|---|---|
| Abrir TCP desde el host PMA al host:puerto del atacante (integridad de la conexión saliente; reconocimiento de ese puerto) | POST /setup/validate.php no autenticado id=Server con Servers/1/host + Servers/1/port más un token de GET / | Probado en laboratorio. El oráculo en oracle:13306 registró PMA-SETUP-VALIDATE-WITNESS desde el contenedor PMA |
| Confirmar que la UI de setup está desactivada mientras validate sigue activo | GET /setup/index.php | Probado en laboratorio. El cuerpo contiene "setup is disabled" / configuration already exists |
| Fallar de forma segura sin el token CSRF de la página de login | Mismo POST, sin token | Probado en laboratorio. Cero impactos en el oráculo |
| Oráculo de puerto / credenciales a partir de errores de mysqli y timing | Mismo testDBConnection | Inferido. El cuerpo del laboratorio fue mysqli_connect(): (HY000/2006): MySQL server has gone away después de que el oráculo aceptó y luego cerró |
| Hablar MySQL a un 3306 interno e intentar el usuario/contraseña enviados | Mismo mysqli_connect | Inferido. No apuntado al servicio db del laboratorio |
ReDoS vía validateRegex interpolando regex de usuario | id=Servers/1/hide_db | Inferido. No ejercitado |
Cerrado en este laboratorio: SSRF de metadatos HTTP (el handshake es MySQL, no GET /latest/meta-data), login PMA no autenticado, shell del SO, y el propio asistente de setup (index.php permanece deshabilitado). FAIL si setup/ no está desplegado (predeterminado de la imagen oficial).
Ocho búsquedas paralelas en el código fuente de RELEASE_5_2_3. setup/index.php tiene el fatal de config-exists. setup/validate.php no. setup/lib/common.inc.php establece $isMinimumCommon y no busca CONFIG_FILE.
Caminos equivocados: tratar la imagen oficial como este remanente (elimina setup/); hacer POST sin el token de la página de login (cero impactos en el oráculo); tratar esto como SSRF de metadatos HTTP (el handshake es MySQL).
python3 phpmyadmin-setup-validate-Abraxas-Labs.py
o
cd lab
./run.sh
Solo loopback: http://127.0.0.1:19230. Proyecto Compose phpmyadmin-setup-validate. El Dockerfile restaura setup/ desde el tarball 5.2.3 y ejecuta un oráculo TCP en el puerto 13306. Testigo PMA-SETUP-VALIDATE-WITNESS.
SUCCESS phpmyadmin-setup-validate how=live tcp=yes setup-index-disabled=yes PMA-SETUP-VALIDATE-WITNESS
Poner el fatal file_exists(CONFIG_FILE) en setup/lib/common.inc.php para que todos los scripts de setup mueran. Restringir los hosts de testDBConnection. No construir delimitadores de preg_match a partir de cadenas de usuario.
962857e)setup/index.php fatal de config-existssetup/validate.php sin esa comprobaciónlibraries/classes/Config/Validator.php testDBConnection / mysqli_connectGNU Affero GPL v3.0. Ver LICENSE. Solo laboratorio loopback. Sin garantía.