
phpMyAdmin 5.2.3 - Alta - Remota - leftover - controllo isSuperUser saltato
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-issuperuser
Classe: Privilegio residuo Raggiungibilità: Remota
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
DatabaseInterface::isSuperUser() non è un controllo SUPER / SYSTEM_USER. È SELECT 1 FROM mysql.user LIMIT 1. Qualsiasi account in grado di leggere mysql.user viene memorizzato nella cache come superuser per il resto della sessione. $cfg['AllowUserDropDatabase'] è impostato su false per impostazione predefinita. DestroyController, SqlController, ImportController e la pagina dei database sfruttano tutti la scorciatoia isSuperUser aggirando quel flag.
Un bypass delle policy di phpMyAdmin, non un nuovo privilegio MySQL. SELECT su mysql.user più DROP, e nessun SUPER, è sufficiente per eseguire Drop tramite PMA.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo |
| Raggiungibilità | Remota (login autenticato tramite cookie come account 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 |
| Prodotto | phpMyAdmin |
| Affetto | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Auth | login autenticato tramite cookie come account MySQL |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Un account MySQL autenticato in grado di leggere mysql.user (tipico SELECT di backup/monitoraggio) più DROP, senza SUPER, viene trattato come superuser di phpMyAdmin.
| Privilegio | Metodo / sink | Ricognizione / integrità / disponibilità | Provato in lab o dedotto |
|---|---|---|---|
Bypass di $cfg['AllowUserDropDatabase']=false e visualizzazione di Drop nella pagina dei database | GET index.php?route=/server/databases | Ricognizione dell'interfaccia Drop | Provato in lab. bulkActionDropButton / selected_dbs[] presenti per selectuser; assenti per plaindrop |
| Drop di un database tramite l'handler destroy di PMA | POST index.php?route=/server/databases/destroy selected_dbs[]=dropme ajax_request=true | Integrità / disponibilità di quel database | Provato in lab. JSON success:true, "1 database has been dropped successfully." dropme eliminato |
Esecuzione di DROP DATABASE dalla casella SQL | POST index.php?route=/sql sql_query=DROP DATABASE \dropme_sql`` | Integrità / disponibilità di quel database | Provato in lab. Database eliminato. L'account negativo riceve "DROP DATABASE statements are disabled." |
Sblocco di altre schermate PMA protette da isSuperUser() | Privilegi, replica, stato, gruppi utente, engine, binlog, variabili | Ricognizione / integrità di quelle schermate | Dedotto dai call site. Non testato |
Lettura di mysql.user | SELECT MySQL che PMA usa come oracolo SUPER | Ricognizione del catalogo che PMA scambia per SUPER | Provato in lab. Quel grant è ciò che il residuo scambia per SUPER |
Chiuso su questo lab: vero SUPER MySQL (SHOW GRANTS rimane USAGE + DROP sulla tabella + SELECT su mysql.user). FILE, GRANT OPTION, shutdown e ALL PRIVILEGES non sono concessi. Un account con DROP ma senza SELECT su mysql.user non può comunque eseguire drop tramite PMA. Non è un nuovo privilegio MySQL e non è RCE.
Stesso pin: WebAuthn CustomServer leftover.
Ho fissato phpMyAdmin RELEASE_5_2_3. I gate sui privilegi che parlano come SUPER dovrebbero comportarsi come SUPER. Questo si comporta come un SELECT sul catalogo:
$result = $this->tryQuery('SELECT 1 FROM mysql.user LIMIT 1');
$isSuperUser = false;
if ($result) {
$isSuperUser = (bool) $result->numRows();
}
SessionCache::set('is_superuser', $isSuperUser);
Gate che usano questo flag attorno a AllowUserDropDatabase (default false):
Controllers/Server/DatabasesController.php is_drop_allowedControllers/Server/Databases/DestroyController.php (destroy AJAX)Controllers/Sql/SqlController.php / Sql::hasNoRightsToDropDatabaseControllers/Import/ImportController.phpControllers/Database/OperationsController.phpVicoli ciechi già registrati: dichiarare un vero SUPER MySQL; trattare un account con solo DROP come il bug (quell'account è il controllo negativo); gonfiare la cosa a RCE; una reverse shell. Teatro.
python3 phpmyadmin-issuperuser-Abraxas-Labs.py
# or: cd lab && ./run.sh
Target solo http://127.0.0.1:19270. Immagini phpmyadmin:5.2.3 e mysql:8.0. Progetto Compose phpmyadmin-issuperuser. $cfg['AllowUserDropDatabase']=false. Lo stack viene smontato dopo l'esecuzione.
selectuser ha SELECT su mysql.user più DROP su dropme / dropme_sql, nessun SUPER. plaindrop ha DROP solo su nodropme. La pagina dei database mostra Drop per selectuser. POST /server/databases/destroy elimina dropme. Anche POST /sql con DROP DATABASE dropme_sql viene eseguito. plaindrop ha comunque ricevuto il JSON di errore da destroy e "DROP DATABASE statements are disabled" da /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
Verificare il vero SUPER / SYSTEM_USER tramite INFORMATION_SCHEMA o SHOW GRANTS. Mantenere un flag separato "può leggere mysql.user" per l'interfaccia che necessita effettivamente di quel catalogo. Non memorizzare nella cache un SELECT sul catalogo come superuser.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/DatabaseInterface.php isSuperUser()GNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.