
Element Web v1.12.29 - Alta - Remota - Sesión - fragmento de credenciales de invitado borra una sesión real antes de whoami
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-fragment-guest
Análisis: https://abraxaslabs.tech/research/element-fragment-guest
Element Web v1.12.29 - Element / New Vector
Clase: Destrucción de sesión Alcance: Remoto
Lifecycle.loadSession prefiere guest_user_id y guest_access_token del hash de la URL por encima de restoreSessionFromStorage. Los invitados están activados por defecto (enableGuest={!config.disable_guests}). El config.json de app.element.io no establece disable_guests. onTokenLoginCompleted elimina únicamente los parámetros SSO y OIDC. Nunca elimina las claves de invitado. url_utils.ts ya comenta que estos parámetros de fragmento parecen no usarse. Aun así prevalecen.
Cualquiera que consiga que un usuario con sesión iniciada abra una URL con hash que contenga parámetros de fragmento de invitado provoca su cierre de sesión y borra la criptografía local. Basta con un token basura. Nunca se llama a whoami.
| ID | aún sin CVE |
| CWE | CWE-384 / CWE-352 / CWE-613 |
| CVSS | Alto: 7.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H |
| Producto | Element Web |
| Afectado | Etiqueta v1.12.29 v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Invitados habilitados (por defecto). |
| Autenticación | atacante no autenticado. La víctima debe abrir (o recargar) una URL. |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
Conseguir que un usuario con sesión iniciada abra una URL con hash que contenga parámetros de fragmento de invitado. El cliente cierra su sesión, borra la criptografía local y puede dejarlo en una sesión de invitado controlada por el atacante. Esto es cierre de sesión y borrado de criptografía. No es robo del token real. No es RCE del sistema operativo.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Demostrado en laboratorio o inferido |
|---|---|---|---|
| Analizar credenciales de invitado desde el hash | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | Integridad de la selección de sesión | Demostrado en laboratorio. #/home?guest_user_id=...&guest_access_token=... se convirtió en guest_params. Solo con cadena de consulta no ocurrió. |
| Preferir invitado sobre una sesión almacenada que no es de invitado | Rama de prioridad de invitado en Lifecycle.loadSession, registro Using guest access credentials | Integridad | Demostrado en laboratorio. La sesión sembrada @victim:example.org no se restauró. |
| Borrar localStorage, cuenta de IndexedDB, sessionStorage, criptografía | doSetLoggedIn(..., clearStorageEnabled=true) y luego clearStorage() | Integridad / disponibilidad de la sesión local | Demostrado en laboratorio. crypto_empty=yes, el token anterior desapareció. |
| Omitir la validación del token | La ruta de invitado nunca llama a /_matrix/client/v3/account/whoami | Integridad | Demostrado en laboratorio. whoami_called=no. El token basura not-a-real-token igualmente provocó el borrado. |
| Persistir las credenciales de invitado del atacante | persistCredentials después del borrado | Integridad | Demostrado en laboratorio. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Fijar la sesión a un invitado real en el HS predeterminado | La misma persistencia si el token de invitado es válido | Integridad | Inferido. El laboratorio usó un token basura, por lo que no hubo inicio de sesión en un HS en vivo. |
| Seguir haciendo esto al recargar | Las claves de invitado permanecen en el hash; onTokenLoginCompleted no las elimina | Integridad | Inferido a partir del pin app.tsx. El laboratorio abrió la URL una vez. |
Cerrado sobre este resto: robar el token de acceso real (está eliminado, no exfiltrado). RCE / LPE del SO (Desktop nodeIntegration: false, sandbox). SPA de Element en vivo (how=gadget). Query-string ?guest_user_id= (solo fragmento). disable_guests: true mantiene la sesión no invitada. Un loadSession parcheado que ignora al invitado cuando existe una sesión no invitada también la mantiene.
Mismos restos del pin: vector: unidad de letra de Windows, Univention ICS javascript: href.
Fijé Element Web v1.12.29 tras la release de GitHub del 22 de septiembre de 2026. El loginToken de SSO es solo de query y se elimina tras su uso. Las claves de invitado siguen en el fragmento y ganan sobre la restauración. El comentario en url_utils.ts es la pista: ya dudaban que estas claves estuvieran especificadas.
Pasos en falso ya registrados: tratar el query-string ?guest_user_id= como el vector (las claves viven en el hash); llamar a esto robo de token (el token real se elimina, no se envía); esperar disable_guests en la configuración de app.element.io (no está definido). Una reverse shell. Teatro.
Gadget de las funciones del pin. No es un contenedor de Element Web en vivo. how=gadget.
python3 element-fragment-guest-Abraxas-Labs.py
o
cd lab
./run.sh
Dirígete solo a http://127.0.0.1:19600. Proyecto de Compose element-fragment-guest. El stack se desmonta después de la ejecución.
SUCCESS element-fragment-guest how=gadget guest-wipe=yes prior-kept=no garbage-token=yes disable-guests-keeps=yes ELEMENT-FRAGMENT-GUEST-WITNESS
Ignorar los parámetros de fragmento de invitado cuando ya existe una sesión que no es de invitado. Validar el token de invitado con /_matrix/client/v3/account/whoami antes de clearStorage. Eliminar guest_user_id y guest_access_token de la misma forma en que se eliminan los tokens SSO. Valor predeterminado disable_guests: true para la instancia alojada app.element.io.