phpMyAdmin 5.2.3 - Élevé - À distance - 2FA - config/set efface l'authentification à deux facteurs
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-config-set-2fa
Classe : Résidu de privilège / étape d'authentification manquante Portée : Distante
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
POST index.php?route=/config/set écrit n'importe quelle préférence autorisée, y compris 2fa. UserPreferences::persistOption n'effectue aucune validation. Settings -> Two-factor appelle toujours TwoFactor::check(true) avant d'accepter de supprimer le facteur. /config/set ne le fait pas.
Une session authentifiée, ou un XSS/CSRF capable de POSTer le jeton de page, peut envoyer key=2fa et value=null. La prochaine connexion par mot de passe n'a ni invite TOTP, WebAuthn, ni Simple. Suppression durable, pas un contournement d'une seule requête.
| ID | pas encore de CVE |
| Classe | Résidu de privilège / étape d'authentification manquante |
| Portée | Distante (connexion par cookie authentifiée ; jeton CSRF requis) |
| CWE | CWE-620 |
| 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 par cookie. Jeton CSRF requis. Permet d'aboutir un XSS ou CSRF vers une suppression durable de la 2FA |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Supprimer la 2FA d'un compte phpMyAdmin sans présenter de TOTP, WebAuthn, ni le champ de confirmation Simple. La prochaine connexion par mot de passe se fait uniquement par mot de passe. Contrôle total de PMA en tant que cet utilisateur MySQL (SQL, utilisateurs, export).
| Privilège | Méthode / chemin | Reconnaissance / intégrité / disponibilité | Prouvé en lab ou déduit |
|---|---|---|---|
Persister 2fa à null et supprimer le second facteur de pmadb | POST index.php?route=/config/set authentifié key=2fa value=null plus un token valide | Intégrité du stockage des préférences | Prouvé en lab. success:true, pmadb config_data est devenu [] |
| Se connecter uniquement par mot de passe après cette écriture | Nouvelle session par cookie, même utilisateur MySQL | Intégrité du chemin de connexion | Prouvé en lab. Pas de 2fa_confirm, arrivée dans l'interface normale |
| Conserver la session en cours pendant que la 2FA disparaît pour les connexions ultérieures | Même handler ; persistOption écrit dans le stockage, pas dans le flag two_factor_check actif | Intégrité des sessions ultérieures | Prouvé en lab. La session A est restée connectée. La session B avait vu la 2FA. La session C ne l'a pas vue |
| Chaîner depuis un XSS stocké ou un CSRF capable de POSTer avec le jeton de page | Résidus de même revue, pas ce lab | Intégrité de la 2FA après un POST same-origin | Déduit |
| Supprimer la 2FA via Settings | POST /preferences/two-factor 2fa_remove=1 | Intégrité de la 2FA via l'interface documentée | Prouvé en lab, fermé. Sans le facteur, PMA affiche la page de confirmation et pmadb contient toujours backend=simple |
Fermé sur ce résidu : accès non authentifié, contournement du mot de passe MySQL, RCE OS, lecture des lignes pmadb d'autres utilisateurs. Je n'ai pas eu besoin du résidu #1 (signature CustomServer). Je n'ai pas contourné le mot de passe MySQL.
Même pin : WebAuthn CustomServer leftover.
J'ai épinglé la 5.2.3 après PMASA-2025-1/2/3. Auth par cookie, pmadb pma__userconfig. Le lab active $cfg['DBG']['simple2fa'] uniquement pour que Settings puisse enrôler le backend Simple sans clé matérielle. TOTP et WebAuthn vivent dans la même clé de préférence 2fa.
SetConfigController prend key et la value JSON et appelle Config::setUserValue. UserPreferences::persistOption est documenté « No validation is done! » apply() autorise 2fa afin que la clé ne soit pas rejetée comme préférence inconnue.
$result = $this->config->setUserValue(null, $key, json_decode($value));
json_decode('null') est null en PHP. persistOption('2fa', null, $default) désactive alors config_data['2fa'] car la valeur par défaut de ce chemin est également null.
Settings -> Two-factor est le contraste. TwoFactorController n'appellera pas configure('') tant que TwoFactor::check(true) ne renvoie pas true.
Fausses pistes déjà consignées : traiter le 2fa_remove de Settings comme la faille (il exige toujours le facteur) ; prétendre à un accès non authentifié ; prétendre à un contournement du mot de passe MySQL ; traiter cela comme le résidu #1 (CustomServer) ; un reverse shell. Du théâtre.
python3 phpmyadmin-config-set-2fa-Abraxas-Labs.py
# or: cd lab && ./run.sh
Cible uniquement http://127.0.0.1:19280. Projet Compose phpmyadmin-config-set-2fa. Pin RELEASE_5_2_3. run.sh copie ou clone ce tag dans lab/src/ pour l'image. La stack est démontée après l'exécution.
Settings a enrôlé la 2FA Simple. Un second navigateur a atteint la page 2fa_confirm. Le POST 2fa_remove sans le facteur est resté sur l'interface de confirmation et a laissé backend=simple dans pmadb. Le POST /config/set a alors renvoyé success:true, pmadb est devenu [], et la connexion suivante a abouti dans l'interface normale.
SUCCESS phpmyadmin-config-set-2fa enroll=simple ui-remove-blocked=yes config-set-cleared=yes next-login-password-only=yes PMA-CONFIG-SET-2FA-WITNESS
Refuser 2fa (et les autres clés d'authentification) sur /config/set. Exiger TwoFactor::check(true) avant toute mutation de la 2FA. Conserver le chemin Settings comme unique écrivain.
962857e4f63d42e38f11ff4d63f5e722018add76)libraries/classes/Controllers/Config/SetConfigController.phplibraries/classes/Config/UserPreferences.phpGNU Affero GPL v3.0. Voir LICENSE. Lab en loopback uniquement. Aucune garantie.