
phpMyAdmin 5.2.3 - Élevé - À distance - Contournement de la 2FA - La cérémonie WebAuthn peut être contournée
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-webauthn
Write-up : https://abraxaslabs.tech/research/phpmyadmin-webauthn
Classe : contournement de 2FA Portée : distante
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3). Tarball par défaut. web-auth/webauthn-lib est en suggest / require-dev. composer install --no-dev ne l'installe pas. createServer utilise donc CustomServer. Cette classe analyse response.signature (le champ doit exister et se décoder) et ne la vérifie jamais via COSE. Elle n'utilise jamais la credentialPublicKey stockée. Le CustomServerTest du produit accepte lui-même une assertion sans clé publique.
Les contrôles structurels sont réels : identifiant de credential dans allowCredentials, clientData.type == webauthn.get, challenge correspondant à la session, hôte d'origine, rpIdHash, user-present. La signature est analysée puis ignorée. Après le mot de passe MySQL, une signature WebAuthn bidon qui correspond quand même à ces champs donne une session phpMyAdmin complète. C'est la base de données. Si vous avez réellement installé web-auth/webauthn-lib, vous êtes sur WebauthnLibServer et non sur ce bug.
| ID | pas encore de CVE |
| Classe | contournement de 2FA / absence de vérification de signature |
| Portée | Distante (connexion par cookie, puis WebAuthn contourné) |
| CWE | CWE-347, CWE-287 |
| 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. Tarball par défaut / composer install --no-dev |
| Auth | Connexion par cookie (mot de passe MySQL), puis WebAuthn contourné |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18080 uniquement |
Il a toujours besoin du mot de passe MySQL (connexion par cookie). Après ce mot de passe, il envoie en POST webauthn_request_response avec un challenge correspondant, l'hôte d'origine, rpIdHash, user-present, l'identifiant de credential enrôlé, et une signature bidon. Il accède à l'interface normale. La 2FA a disparu. C'est la base de données (SQL, utilisateurs, export), pas un shell PHP sur l'hôte.
Si vous avez réellement installé web-auth/webauthn-lib, vous êtes sur WebauthnLibServer et non sur ce bug.
| Privilège | Méthode / chemin | Prouvé en lab ou déduit |
|---|---|---|
| Contourner complètement la 2FA WebAuthn sans l'authentificateur (intégrité du second facteur) | POST webauthn_request_response après le mot de passe, signature bidon | Prouvé en lab. still_2fa=False landed=True |
| PMA complet en tant que cet utilisateur MySQL (intégrité + reconnaissance de la machine SQL) | même session | Prouvé en lab. Marqueurs de l'interface d'accueil présents |
| Contourner le mot de passe MySQL | POST non authentifié | Prouvé en lab, fermé. Reste sur la page de connexion |
Même contournement avec web-auth/webauthn-lib installé | WebauthnLibServer | Fermé. Ce n'est pas ce reliquat |
| RCE OS / reverse shell | ce reliquat | Fermé |
Fermés sur ce reliquat : PMA non authentifié, un shell PHP sur l'hôte, et le fait de traiter un tarball qui a réellement installé web-auth/webauthn-lib comme ce bug.
J'ai lu createServer, puis parseAndValidateAssertionResponse, puis le test unitaire qui ne passe pas de clé publique. Les contrôles structurels sont réels. La signature est analysée puis ignorée.
Fausses pistes : envoyer en POST du JSON WebAuthn sans session préalable avec mot de passe ; une signature qui échouait aux contrôles structurels ; Webauthn\Server toujours présent (mauvaise classe de serveur) ; challenge ne provenant pas de cette session ; incohérence de l'hôte d'origine ; indicateur user-present absent ; identifiant de credential absent de allowCredentials.
Le Dockerfile du lab copie 5.2.3, exécute composer install --no-dev, puis supprime vendor/web-auth afin que CustomServer soit celui utilisé. Le dernier php -r se termine avec le code 1 si Webauthn\Server existe. init.sql enrôle la 2FA WebAuthn pour appuser sans clé matérielle. Le PoC envoie en POST la signature not-a-real-signature-PMA-WEBAUTHN-BYPASS.
Clonez le pin à côté du Dockerfile, puis exécutez :
cd lab
git clone --depth 1 --branch RELEASE_5_2_3 https://github.com/phpmyadmin/phpmyadmin.git src
./run.sh
ou depuis la racine du pack après ce clone :
python3 phpmyadmin-webauthn-Abraxas-Labs.py
Loopback uniquement : http://127.0.0.1:18080. Projet Compose pma-webauthn-lab. Épingler RELEASE_5_2_3. Ne pas livrer src/. Témoin PMA-WEBAUTHN-BYPASS.
SUCCESS PMA-WEBAUTHN-BYPASS WebAuthn 2FA accepted with garbage signature
Vérifiez authenticatorData || SHA-256(clientDataJSON) avec la clé publique COSE stockée ; liez userHandle ; appliquez signCount. Faites de web-auth/webauthn-lib une véritable dépendance et supprimez CustomServer, ou échouez en mode fermé si la bibliothèque est absente. D'ici là, désactivez la 2FA WebAuthn ou n'exposez pas ce phpMyAdmin.
Plugins\TwoFactor\WebAuthn::createServerCustomServer::parseAndValidateAssertionResponseGNU Affero GPL v3.0. Voir LICENSE. Laboratoire en boucle locale uniquement. Aucune garantie.