
phpMyAdmin 5.2.3 - High - Remote - leftover - isSuperUser check skipped
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-issuperuser
Class: Privilege leftover Reach: Remote
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
DatabaseInterface::isSuperUser() is not a SUPER / SYSTEM_USER check. It is SELECT 1 FROM mysql.user LIMIT 1. Any account that can read mysql.user is cached as a superuser for the rest of the session. $cfg['AllowUserDropDatabase'] defaults to false. DestroyController, SqlController, ImportController, and the databases page all take the isSuperUser shortcut around that flag.
A phpMyAdmin policy bypass, not a new MySQL privilege. SELECT on mysql.user plus DROP, and no SUPER, is enough to Drop through PMA.
| ID | no CVE yet |
| Class | Privilege leftover |
| Reach | Remote (authenticated cookie login as a MySQL account) |
| CWE | CWE-863 |
| CVSS | Medium: 6.3 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L |
| Product | phpMyAdmin |
| Affected | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Auth | authenticated cookie login as a MySQL account |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only |
A signed-in MySQL account that can read mysql.user (typical backup/monitor SELECT) plus DROP, without SUPER, is treated as a phpMyAdmin superuser.
| Privilege | Method / sink | Recon / integrity / availability | Lab-proven or inferred |
|---|---|---|---|
Bypass $cfg['AllowUserDropDatabase']=false and see Drop on the databases page | GET index.php?route=/server/databases | Recon of the Drop UI | Lab-proven. bulkActionDropButton / selected_dbs[] present for selectuser; absent for plaindrop |
| Drop a database through the PMA destroy handler | POST index.php?route=/server/databases/destroy selected_dbs[]=dropme ajax_request=true | Integrity / availability of that database | Lab-proven. JSON success:true, "1 database has been dropped successfully." dropme gone |
Run DROP DATABASE from the SQL box | POST index.php?route=/sql sql_query=DROP DATABASE \dropme_sql`` | Integrity / availability of that database | Lab-proven. Database gone. Negative account gets "DROP DATABASE statements are disabled." |
Unlock other PMA screens gated on isSuperUser() | Privileges, replication, status, user groups, engines, binlog, variables | Recon / integrity of those screens | Inferred from call sites. Not exercised |
Read mysql.user | MySQL SELECT that PMA uses as the SUPER oracle | Recon of the catalog PMA mistakes for SUPER | Lab-proven. That grant is what the leftover mistakes for SUPER |
Closed on this lab: real MySQL SUPER (SHOW GRANTS stays USAGE + table DROP + SELECT on mysql.user). FILE, GRANT OPTION, shutdown, and ALL PRIVILEGES are not granted. An account with DROP but no SELECT on mysql.user still cannot drop through PMA. This is not a new MySQL privilege and not RCE.
Same pin: WebAuthn CustomServer leftover.
I pinned phpMyAdmin RELEASE_5_2_3. Privilege gates that talk like SUPER should look like SUPER. This one looks like a catalog SELECT:
$result = $this->tryQuery('SELECT 1 FROM mysql.user LIMIT 1');
$isSuperUser = false;
if ($result) {
$isSuperUser = (bool) $result->numRows();
}
SessionCache::set('is_superuser', $isSuperUser);
Gates that take this flag around AllowUserDropDatabase (default false):
Controllers/Server/DatabasesController.php is_drop_allowedControllers/Server/Databases/DestroyController.php (AJAX destroy)Controllers/Sql/SqlController.php / Sql::hasNoRightsToDropDatabaseControllers/Import/ImportController.phpControllers/Database/OperationsController.phpWrong turns already recorded: claiming real MySQL SUPER; treating a DROP-only account as the bug (that account is the negative control); inflating this to RCE; a reverse shell. Theatre.
python3 phpmyadmin-issuperuser-Abraxas-Labs.py
# or: cd lab && ./run.sh
Target only http://127.0.0.1:19270. Images phpmyadmin:5.2.3 and mysql:8.0. Compose project phpmyadmin-issuperuser. $cfg['AllowUserDropDatabase']=false. Stack tears down after the run.
selectuser has SELECT on mysql.user plus DROP on dropme / dropme_sql, no SUPER. plaindrop has DROP on nodropme only. Databases page draws Drop for selectuser. POST /server/databases/destroy drops dropme. POST /sql with DROP DATABASE dropme_sql runs too. plaindrop still got the Error JSON from destroy and "DROP DATABASE statements are disabled" from /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
Test real SUPER / SYSTEM_USER via INFORMATION_SCHEMA or SHOW GRANTS. Keep a separate "can read mysql.user" flag for UI that actually needs that catalog. Do not cache a catalog SELECT as superuser.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/DatabaseInterface.php isSuperUser()GNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.