
phpMyAdmin 5.2.3 - Alta - Remota - residual - comprobación isSuperUser omitida
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-issuperuser
Análisis: https://abraxaslabs.tech/research/phpmyadmin-issuperuser
Clase: Privilegio residual Alcance: Remoto
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
DatabaseInterface::isSuperUser() no es una comprobación de SUPER / SYSTEM_USER. Es SELECT 1 FROM mysql.user LIMIT 1. Cualquier cuenta que pueda leer mysql.user queda almacenada en caché como superusuario durante el resto de la sesión. $cfg['AllowUserDropDatabase'] es false por defecto. DestroyController, SqlController, ImportController y la página de bases de datos toman el atajo de isSuperUser sorteando ese flag.
Un bypass de la política de phpMyAdmin, no un nuevo privilegio de MySQL. SELECT sobre mysql.user más DROP, y sin SUPER, es suficiente para hacer Drop a través de PMA.
| ID | aún sin CVE |
| Clase | Privilegio residual |
| Alcance | Remoto (inicio de sesión autenticado por cookie como una cuenta de MySQL) |
| CWE | CWE-863 |
| CVSS | Medio: 6.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L |
| Producto | phpMyAdmin |
| Afectado | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Autenticación | inicio de sesión autenticado por cookie como una cuenta de MySQL |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Una cuenta de MySQL con sesión iniciada que puede leer mysql.user (típico SELECT de backup/monitorización) más DROP, sin SUPER, es tratada como superusuario de phpMyAdmin.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en laboratorio o inferido |
|---|---|---|---|
Eludir $cfg['AllowUserDropDatabase']=false y ver Drop en la página de bases de datos | GET index.php?route=/server/databases | Reconocimiento de la interfaz de Drop | Probado en laboratorio. bulkActionDropButton / selected_dbs[] presentes para selectuser; ausentes para plaindrop |
| Eliminar una base de datos mediante el manejador destroy de PMA | POST index.php?route=/server/databases/destroy selected_dbs[]=dropme ajax_request=true | Integridad / disponibilidad de esa base de datos | Probado en laboratorio. JSON success:true, "1 database has been dropped successfully." dropme eliminada |
Ejecutar DROP DATABASE desde el cuadro SQL | POST index.php?route=/sql sql_query=DROP DATABASE \dropme_sql`` | Integridad / disponibilidad de esa base de datos | Probado en laboratorio. Base de datos eliminada. La cuenta negativa recibe "DROP DATABASE statements are disabled." |
Desbloquear otras pantallas de PMA condicionadas a isSuperUser() | Privilegios, replicación, estado, grupos de usuarios, motores, binlog, variables | Reconocimiento / integridad de esas pantallas | Inferido a partir de los puntos de llamada. No ejercitado |
Leer mysql.user | SELECT de MySQL que PMA usa como oráculo de SUPER | Reconocimiento del catálogo que PMA confunde con SUPER | Probado en laboratorio. Ese grant es lo que el residual confunde con SUPER |
Cerrado en este laboratorio: SUPER real de MySQL (SHOW GRANTS permanece como USAGE + DROP de tabla + SELECT sobre mysql.user). FILE, GRANT OPTION, shutdown y ALL PRIVILEGES no están concedidos. Una cuenta con DROP pero sin SELECT sobre mysql.user sigue sin poder eliminar a través de PMA. Esto no es un nuevo privilegio de MySQL ni RCE.
Mismo pin: Residual de WebAuthn CustomServer.
Fijé phpMyAdmin RELEASE_5_2_3. Las comprobaciones de privilegios que dicen comportarse como SUPER deberían parecerse a SUPER. Esta se parece a un SELECT de catálogo:
$result = $this->tryQuery('SELECT 1 FROM mysql.user LIMIT 1');
$isSuperUser = false;
if ($result) {
$isSuperUser = (bool) $result->numRows();
}
SessionCache::set('is_superuser', $isSuperUser);
Puertas que usan este flag en torno a AllowUserDropDatabase (por defecto false):
Controllers/Server/DatabasesController.php is_drop_allowedControllers/Server/Databases/DestroyController.php (destrucción AJAX)Controllers/Sql/SqlController.php / Sql::hasNoRightsToDropDatabaseControllers/Import/ImportController.phpControllers/Database/OperationsController.phpDesvíos ya registrados: afirmar que se trata de un SUPER real de MySQL; tratar una cuenta solo con DROP como el fallo (esa cuenta es el control negativo); inflar esto a RCE; una reverse shell. Teatro.
python3 phpmyadmin-issuperuser-Abraxas-Labs.py
# or: cd lab && ./run.sh
Dirígete solo a http://127.0.0.1:19270. Imágenes phpmyadmin:5.2.3 y mysql:8.0. Proyecto de Compose phpmyadmin-issuperuser. $cfg['AllowUserDropDatabase']=false. El stack se desmonta tras la ejecución.
selectuser tiene SELECT sobre mysql.user además de DROP sobre dropme / dropme_sql, sin SUPER. plaindrop tiene DROP solo sobre nodropme. La página de bases de datos muestra Drop para selectuser. POST /server/databases/destroy elimina dropme. POST /sql con DROP DATABASE dropme_sql también se ejecuta. plaindrop siguió recibiendo el JSON de Error de destroy y "DROP DATABASE statements are disabled" de /sql.
SUCCESS phpmyadmin-issuperuser drop-ui=yes destroy=ok sql-drop=ok grants-no-super=yes mysql.user-select=yes neg-drop-ui=no neg-destroy=denied PMA-ISSUPERUSER-WITNESS
Prueba SUPER / SYSTEM_USER reales mediante INFORMATION_SCHEMA o SHOW GRANTS. Mantén un indicador separado de "puede leer mysql.user" para la interfaz que realmente necesita ese catálogo. No almacenes en caché un SELECT de catálogo como superusuario.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/DatabaseInterface.php isSuperUser()GNU Affero GPL v3.0. Consulta LICENSE. Solo para laboratorio en loopback. Sin garantía.