
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
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 sobre 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 del fragmento parecen no usarse. Aun así ganan.
Cualquiera que pueda conseguir que un usuario con sesión iniciada abra una URL con hash con parámetros de fragmento de invitado lo desconecta y borra la criptografía local. Un token basura es suficiente. Nunca se llama a whoami.
| ID | sin CVE todavía |
| 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 | v1.12.29 tag v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Invitados habilitados (por defecto). |
| Auth | atacante no autenticado. La víctima debe abrir (o recargar) una URL. |
| Licencia | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Conseguir que un usuario con sesión iniciada abra una URL con hash con parámetros de fragmento de invitado. El cliente lo desconecta, borra la criptografía local y puede dejarlo en un invitado del atacante. Esto es cierre de sesión y borrado de criptografía. No es robar el token real. No es RCE del sistema operativo.
| Privilegio | Método / sink | Reconocimiento / integridad / disponibilidad | Probado en lab o inferido |
|---|---|---|---|
| Parsear 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 | Probado en lab. #/home?guest_user_id=...&guest_access_token=... se convirtió en guest_params. Solo con query-string no. |
| Preferir invitado sobre una sesión no invitada almacenada | Rama guest-first de Lifecycle.loadSession, log Using guest access credentials | Integridad | Probado en lab. El @victim:example.org sembrado no se restauró. |
| Borrar localStorage, cuenta de IndexedDB, sessionStorage, criptografía | doSetLoggedIn(..., clearStorageEnabled=true) luego clearStorage() | Integridad / disponibilidad de la sesión local | Probado en lab. crypto_empty=yes, el token previo desapareció. |
| Omitir la validación del token | La ruta de invitado nunca llama a /_matrix/client/v3/account/whoami | Integridad | Probado en lab. whoami_called=no. El token basura not-a-real-token igualmente borró. |
| Persistir las credenciales de invitado del atacante | persistCredentials después del borrado | Integridad | Probado en lab. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Fijar sobre un invitado real en el HS por defecto | Mismo persist si el token de invitado es válido | Integridad | Inferido. El lab usó un token basura, así que no hubo login en un HS real. |
| Seguir haciendo esto al recargar | Las claves de invitado permanecen en el hash; onTokenLoginCompleted no las elimina | Integridad | Inferido del pin app.tsx. El lab abrió la URL una vez. |
Descartado en este remanente: robar el token de acceso real (se elimina, no se exfiltra). RCE del SO / LPE (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.
Otros remanentes del mismo pin: vector: letra de unidad de Windows, Univention ICS javascript: href.
Fijé Element Web v1.12.29 tras el lanzamiento de GitHub del 22 de septiembre de 2026. El loginToken de SSO es solo 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 de que estas claves estuvieran especificadas.
Caminos equivocados 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 config de app.element.io (no está establecido). 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
Objetivo solo http://127.0.0.1:19600. Proyecto de Compose element-fragment-guest. El stack se desmonta tras 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 no invitada. 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. Establecer disable_guests: true por defecto para el app.element.io alojado.
Lifecycle.ts (loadSession guest-first)url_utils.tsapp.tsx (enableGuest={!config.disable_guests})GNU Affero GPL v3.0. Ver LICENSE. Solo lab en loopback. Sin garantía.