
phpMyAdmin 5.2.3 - Alta - Remota - residual - comprobación isSuperUser omitida
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · 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 se almacena 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 isSuperUser alrededor de 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 | sin CVE todavía |
| Clase | Privilegio residual |
| Alcance | Remoto (inicio de sesión autenticado con 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 con 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 a través del 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 desaparecida |
Ejecutar DROP DATABASE desde la caja 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 USAGE + DROP de tabla + SELECT sobre mysql.user). FILE, GRANT OPTION, shutdown y ALL PRIVILEGES no están otorgados. Una cuenta con DROP pero sin SELECT sobre mysql.user sigue sin poder hacer drop a través de PMA. Esto no es un nuevo privilegio de MySQL ni RCE.
Mismo pin: WebAuthn CustomServer leftover.
Fijé phpMyAdmin RELEASE_5_2_3. Las puertas de privilegios que hablan 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 toman este flag alrededor de AllowUserDropDatabase (false por defecto):
Controllers/Server/DatabasesController.php is_drop_allowedControllers/Server/Databases/DestroyController.php (destroy AJAX)Controllers/Sql/SqlController.php / Sql::hasNoRightsToDropDatabaseControllers/Import/ImportController.phpControllers/Database/OperationsController.phpCaminos equivocados ya registrados: afirmar SUPER real de MySQL; tratar una cuenta solo con DROP como el bug (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
Objetivo solo http://127.0.0.1:19270. Imágenes phpmyadmin:5.2.3 y mysql:8.0. Proyecto Compose phpmyadmin-issuperuser. $cfg['AllowUserDropDatabase']=false. El stack se desmonta tras la ejecución.
selectuser tiene SELECT sobre mysql.user más DROP sobre dropme / dropme_sql, sin SUPER. plaindrop tiene DROP solo sobre nodropme. La página de bases de datos dibuja 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
Comprobar SUPER / SYSTEM_USER reales mediante INFORMATION_SCHEMA o SHOW GRANTS. Mantener un flag separado de "puede leer mysql.user" para la interfaz que realmente necesita ese catálogo. No almacenar en caché un SELECT de catálogo como superusuario.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/DatabaseInterface.php isSuperUser()GNU Affero GPL v3.0. Ver LICENSE. Solo laboratorio en loopback. Sin garantía.