phpMyAdmin 5.2.3 - Élevé - À distance - SQLi - identifiant du plugin d'authentification non échappé
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-auth-plugin-unquoted
Write-up : https://abraxaslabs.tech/research/phpmyadmin-auth-plugin-unquoted
Classe : SQLi Portée : Distante
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
Le changement de mot de passe est activé par défaut. UserPassword.php copie le champ POST authentication_plugin dans ALTER USER ... IDENTIFIED WITH sans liste d'autorisation ni mise entre guillemets. Le nom d'utilisateur, l'hôte et le mot de passe de la même instruction passent par escapeString. Sur MySQL 8, la clause WITH est émise lorsque le plugin envoyé diffère du plugin actuel.
Un utilisateur phpMyAdmin connecté injecte du SQL dans son propre ALTER USER via le formulaire de changement de mot de passe. Le SQL supplémentaire dans le champ plugin est du SQL, pas un nom de plugin.
| ID | pas encore de CVE |
| Classe | SQLi |
| Portée | Distante (connexion authentifiée par cookie ; changement de mot de passe activé) |
| CWE | CWE-89 |
| CVSS | Élevé : 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Produit | phpMyAdmin |
| Affecté | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Auth | connexion authentifiée par cookie. $cfg['ShowChgPassword'] vaut true par défaut. Le type d'authentification n'est pas config |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Un utilisateur phpMyAdmin connecté peut injecter du SQL dans son propre ALTER USER via le formulaire de changement de mot de passe.
| Privilège | Méthode / sink | Reconnaissance / intégrité / disponibilité | Prouvé en lab ou déduit |
|---|---|---|---|
Envoyer du SQL supplémentaire dans IDENTIFIED WITH | POST index.php?route=/user-password avec authentication_plugin | Intégrité de l'instruction construite par phpMyAdmin | Prouvé en lab. Le POST brut sha256_password /*PMA-AUTH-PLUGIN-UNQUOTED-WITNESS*/ apparaît sans guillemets dans la zone SQL |
| Faire parser ce SQL supplémentaire comme du SQL par MySQL | La même instruction atteint mysqld | Intégrité de la connexion de l'utilisateur | Prouvé en lab. Le journal général a conservé le plugin sha256_password et supprimé le commentaire. 1227 car cet utilisateur n'a pas CREATE USER |
| Clauses supplémentaires ou comptes supplémentaires si l'évasion est parsée | Même sink ; les requêtes empilées dépendent du driver | Intégrité d'autres comptes | Déduit. Ce lab n'exécute pas de seconde instruction ni ne crée d'autre compte |
| Même concaténation sur l'ajout/édition d'utilisateur | Privileges.php IDENTIFIED WITH / MariaDB VIA | Intégrité des instructions construites par le grantor | Variante déduite. Le POST du lab concerne uniquement le changement de mot de passe |
Fermé sur ce chemin : usage non authentifié (connexion par cookie requise), auth config (le changement de mot de passe est masqué), RCE, changement de plugin sans GRANT réussi sur MySQL 8 (1227 sans CREATE USER). Le nom d'utilisateur, l'hôte et le mot de passe restent échappés. Le mot de passe personnel ne nécessite pas de GRANT ; le résidu est le champ plugin non échappé, pas un échange de plugin libre.
Même pin : WebAuthn CustomServer leftover.
J'ai épinglé phpmyadmin/phpmyadmin RELEASE_5_2_3. PMASA-2025-1/2/3 sont déjà dans 5.2.2. Le changement de mot de passe construit toujours :
return 'ALTER USER \'' . $dbi->escapeString($username)
. '\'@\'' . $dbi->escapeString($hostname)
. '\' IDENTIFIED WITH ' . $authPlugin . ' BY '
$authPlugin est $_POST['authentication_plugin']. MySQL 5.7.37+ et 8.0 omettent WITH sauf si le plugin a changé. Envoyez un autre nom en POST et la clause réapparaît.
Fausses pistes déjà consignées : traiter MySQL 1227 comme un échec du leftover (c'est la preuve que du SQL supplémentaire a été analysé) ; affirmer un changement de plugin sans GRANT sur MySQL 8 ; considérer l'auth par config comme dans le périmètre ; un reverse shell. Du théâtre.
python3 phpmyadmin-auth-plugin-unquoted-Abraxas-Labs.py
# or: cd lab && ./run.sh
Cibler uniquement http://127.0.0.1:19260. Images phpmyadmin:5.2.3 et mysql:8.0. Projet Compose phpmyadmin-auth-plugin-unquoted. La stack est démontée après l'exécution.
Connexion par cookie en tant que appuser. POST /user-password avec authentication_plugin=sha256_password /*PMA-AUTH-PLUGIN-UNQUOTED-WITNESS*/. Zone de requête SQL de PMA : ALTER USER 'appuser'@'%' IDENTIFIED WITH sha256_password /*PMA-AUTH-PLUGIN-UNQUOTED-WITNESS*/ BY '***'. Le journal général de MySQL analyse le commentaire et stocke IDENTIFIED WITH 'sha256_password'. Le nom d'utilisateur est entre guillemets.
SUCCESS phpmyadmin-auth-plugin-unquoted how=live unquoted=yes escaped-user=yes plugin=sha256_password PMA-AUTH-PLUGIN-UNQUOTED-WITNESS
Autoriser par liste blanche les noms de plugins issus de SHOW PLUGINS. Ne jamais interpoler POST dans IDENTIFIED WITH, VIA ou plugin=.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/UserPassword.phplibraries/classes/Server/Privileges.phpGNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.