
Element Web v1.12.29 - Élevé - À distance - Session - fragment guest creds wipe a real session before whoami
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-fragment-guest
Element Web v1.12.29 - Element / New Vector
Classe : Destruction de session Portée : Distante
Lifecycle.loadSession privilégie guest_user_id et guest_access_token issus du fragment d'URL plutôt que restoreSessionFromStorage. Les invités sont activés par défaut (enableGuest={!config.disable_guests}). Le config.json d'app.element.io ne définit pas disable_guests. onTokenLoginCompleted ne supprime que les paramètres SSO et OIDC. Il ne supprime jamais les clés invité. url_utils.ts commente déjà que ces paramètres de fragment semblent inutilisés. Ils l'emportent quand même.
Quiconque peut amener un utilisateur connecté à ouvrir une URL avec des paramètres de fragment invité le déconnecte et efface la cryptographie locale. Un jeton bidon suffit. whoami n'est jamais appelé.
| ID | pas encore de CVE |
| CWE | CWE-384 / CWE-352 / CWE-613 |
| CVSS | Élevé : 7.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H |
| Produit | Element Web |
| Affecté | v1.12.29 tag v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Invités activés (par défaut). |
| Auth | attaquant non authentifié. La victime doit ouvrir (ou recharger) une URL. |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1 uniquement |
Amener un utilisateur connecté à ouvrir une URL avec des paramètres de fragment invité. Le client le déconnecte, efface la cryptographie locale et peut le placer sur un invité contrôlé par l'attaquant. Il s'agit d'une déconnexion et d'un effacement cryptographique. Ce n'est pas un vol du vrai jeton. Ce n'est pas une RCE système.
| Privilège | Méthode / sink | Reconnaissance / intégrité / disponibilité | Prouvé en labo ou déduit |
|---|---|---|---|
| Analyser les identifiants invité depuis le fragment | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | Intégrité de la sélection de session | Prouvé en labo. #/home?guest_user_id=...&guest_access_token=... est devenu guest_params. La chaîne de requête seule ne l'a pas fait. |
| Privilégier l'invité sur une session non-invité stockée | Branche invité-prioritaire de Lifecycle.loadSession, journal Using guest access credentials | Intégrité | Prouvé en labo. @victim:example.org préchargé n'a pas été restauré. |
| Effacer localStorage, compte IndexedDB, sessionStorage, crypto | doSetLoggedIn(..., clearStorageEnabled=true) puis clearStorage() | Intégrité / disponibilité de la session locale | Prouvé en labo. crypto_empty=yes, jeton précédent disparu. |
| Contourner la validation du jeton | Le chemin invité n'appelle jamais /_matrix/client/v3/account/whoami | Intégrité | Prouvé en labo. whoami_called=no. Le jeton bidon not-a-real-token a quand même tout effacé. |
| Persister les identifiants invité de l'attaquant | persistCredentials après l'effacement | Intégrité | Prouvé en labo. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Fixer sur un vrai invité sur le HS par défaut | Même persistance si le jeton invité est valide | Intégrité | Déduit. Le labo a utilisé un jeton bidon, donc pas de connexion HS réelle. |
| Continuer à le faire au rechargement | Les clés invité restent dans le fragment ; onTokenLoginCompleted ne les supprime pas | Intégrité | Déduit du pin app.tsx. Le labo a ouvert l'URL une fois. |
Écarté sur ce reste : voler le vrai jeton d'accès (il est supprimé, pas exfiltré). RCE système / LPE (Desktop nodeIntegration: false, sandbox). SPA Element en direct (how=gadget). Chaîne de requête ?guest_user_id= (fragment uniquement). disable_guests: true conserve la session non-invité. Un loadSession corrigé qui ignore l'invité lorsqu'une session non-invité existe la conserve aussi.
Autres restes du même pin : vector: lettre de lecteur Windows, Univention ICS javascript: href.
J'ai épinglé Element Web v1.12.29 après la publication GitHub du 22 septembre 2026. Le loginToken SSO est uniquement en chaîne de requête et supprimé après usage. Les clés invité restent dans le fragment et l'emportent sur la restauration. Le commentaire dans url_utils.ts est l'indice : ils doutaient déjà que ces clés soient spécifiées.
Fausses pistes déjà consignées : traiter la chaîne de requête ?guest_user_id= comme le vecteur (les clés vivent dans le fragment) ; qualifier cela de vol de jeton (le vrai jeton est supprimé, pas envoyé) ; s'attendre à disable_guests dans la config d'app.element.io (il n'est pas défini). Un reverse shell. Du théâtre.
Gadget des fonctions du pin. Pas un conteneur Element Web réel. how=gadget.
python3 element-fragment-guest-Abraxas-Labs.py
ou
cd lab
./run.sh
Cible uniquement http://127.0.0.1:19600. Projet Compose element-fragment-guest. La pile est démontée après l'exécution.
SUCCESS element-fragment-guest how=gadget guest-wipe=yes prior-kept=no garbage-token=yes disable-guests-keeps=yes ELEMENT-FRAGMENT-GUEST-WITNESS
Ignorer les paramètres de fragment invité lorsqu'une session non-invité existe déjà. Valider le jeton invité avec /_matrix/client/v3/account/whoami avant clearStorage. Supprimer guest_user_id et guest_access_token de la même manière que les jetons SSO sont supprimés. Définir disable_guests: true par défaut pour app.element.io hébergé.
Lifecycle.ts (loadSession invité-prioritaire)url_utils.tsapp.tsx (enableGuest={!config.disable_guests})GNU Affero GPL v3.0. Voir LICENSE. Labo en boucle locale uniquement. Aucune garantie.