
phpMyAdmin 5.2.3 - Alta - Remota - Omisión de 2FA - Se puede omitir la ceremonia de WebAuthn
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-webauthn
Write-up: https://abraxaslabs.tech/research/phpmyadmin-webauthn
Clase: bypass de 2FA Alcance: Remoto
phpMyAdmin 5.2.3 (tag RELEASE_5_2_3). Tarball por defecto. web-auth/webauthn-lib es suggest / require-dev. composer install --no-dev no lo instala. Por lo tanto, createServer usa CustomServer. Esa clase parsea response.signature (el campo debe existir y decodificar) y nunca lo verifica con COSE. Nunca usa la credentialPublicKey almacenada. El propio CustomServerTest del producto acepta una aserción sin clave pública.
Las comprobaciones estructurales son reales: id de credencial en allowCredentials, clientData.type == webauthn.get, challenge coincide con la sesión, host de origen, rpIdHash, user-present. La firma se parsea y se ignora. Tras la contraseña de MySQL, una firma WebAuthn basura que aún coincida con esos campos es una sesión completa de phpMyAdmin. Eso es la base de datos. Si realmente instalaste web-auth/webauthn-lib, estás en WebauthnLibServer y no en este bug.
| ID | aún sin CVE |
| Clase | bypass de 2FA / verificación de firma ausente |
| Alcance | Remoto (login por cookie, luego WebAuthn omitido) |
| CWE | CWE-347, CWE-287 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Producto | phpMyAdmin |
| Afectado | 5.2.3 tag RELEASE_5_2_3. Tarball por defecto / composer install --no-dev |
| Autenticación | Login por cookie (contraseña de MySQL), luego WebAuthn omitido |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1:18080 |
Todavía necesita la contraseña de MySQL (login por cookie). Tras esa contraseña, envía por POST webauthn_request_response con challenge coincidente, host de origen, rpIdHash, user-present, id de credencial registrada y una firma basura. Aterriza en la interfaz normal. El 2FA ha desaparecido. Eso es la base de datos (SQL, usuarios, exportación), no una shell PHP en el host.
Si realmente instalaste web-auth/webauthn-lib, estás en WebauthnLibServer y no en este bug.
| Privilegio | Método / ruta | Probado en laboratorio o inferido |
|---|---|---|
| Completar el 2FA WebAuthn sin el autenticador (integridad del segundo factor) | POST webauthn_request_response tras la contraseña, firma basura | Probado en laboratorio. still_2fa=False landed=True |
| PMA completo como ese usuario de MySQL (integridad + reconocimiento del servidor SQL) | misma sesión | Probado en laboratorio. Marcadores de la interfaz de inicio presentes |
| Omitir la contraseña de MySQL | POST no autenticado | Probado en laboratorio, cerrado. Permanece en el login |
Mismo bypass con web-auth/webauthn-lib instalado | WebauthnLibServer | Cerrado. No es este remanente |
| RCE en el SO / reverse shell | este remanente | Cerrado |
Cerrado en este remanente: PMA no autenticado, una shell PHP en el host, y tratar un tarball que realmente instaló web-auth/webauthn-lib como este bug.
Leí createServer, luego parseAndValidateAssertionResponse, luego el test unitario que no pasa una clave pública. Las comprobaciones estructurales son reales. La firma se parsea y se ignora.
Caminos equivocados: enviar por POST JSON de WebAuthn sin una sesión de contraseña previa; una firma que fallaba las comprobaciones estructurales; Webauthn\Server aún presente (clase de servidor equivocada); challenge que no era de esta sesión; host de origen no coincidente; flag user-present desactivado; id de credencial no presente en allowCredentials.
El Dockerfile del laboratorio copia 5.2.3, ejecuta composer install --no-dev y luego elimina vendor/web-auth para que CustomServer sea el que esté en juego. El último php -r sale con código 1 si existe Webauthn\Server. init.sql inscribe la 2FA de WebAuthn para appuser sin una clave de hardware. El PoC envía por POST la firma not-a-real-signature-PMA-WEBAUTHN-BYPASS.
Clona el pin junto al Dockerfile y luego ejecuta:
cd lab
git clone --depth 1 --branch RELEASE_5_2_3 https://github.com/phpmyadmin/phpmyadmin.git src
./run.sh
o desde la raíz del paquete después de ese clon:
python3 phpmyadmin-webauthn-Abraxas-Labs.py
Solo loopback: http://127.0.0.1:18080. Proyecto Compose pma-webauthn-lab. Fijar RELEASE_5_2_3. No distribuir src/. Testigo PMA-WEBAUTHN-BYPASS.
SUCCESS PMA-WEBAUTHN-BYPASS WebAuthn 2FA accepted with garbage signature
Verificar authenticatorData || SHA-256(clientDataJSON) con la clave pública COSE almacenada; vincular userHandle; aplicar signCount. Convertir web-auth/webauthn-lib en una dependencia real y eliminar CustomServer, o fallar de forma segura si la biblioteca no está presente. Hasta entonces, deshabilitar el 2FA de WebAuthn o no exponer este phpMyAdmin.
Plugins\TwoFactor\WebAuthn::createServerCustomServer::parseAndValidateAssertionResponseGNU Affero GPL v3.0. Véase LICENSE. Solo para laboratorio en loopback. Sin garantía.