
Element Web v1.12.29 - Alto - Remoto - Sessão - fragmento de credenciais de convidado apaga uma sessão real antes do whoami
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-fragment-guest
Element Web v1.12.29 - Element / New Vector
Classe: Destruição de sessão Alcance: Remoto
Lifecycle.loadSession prefere guest_user_id e guest_access_token do hash da URL em vez de restoreSessionFromStorage. Convidados estão ativados por padrão (enableGuest={!config.disable_guests}). O config.json do app.element.io não define disable_guests. onTokenLoginCompleted remove apenas parâmetros SSO e OIDC. Nunca remove as chaves de convidado. url_utils.ts já comenta que esses parâmetros de fragmento parecem não ser usados. Ainda assim, eles vencem.
Qualquer pessoa que consiga fazer um usuário autenticado abrir uma URL com hash contendo parâmetros de fragmento de convidado o desconecta e apaga a criptografia local. Um token inválido é suficiente. whoami nunca é chamado.
| ID | sem CVE ainda |
| 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 |
| Produto | Element Web |
| Afetado | v1.12.29 tag v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Convidados ativados (padrão). |
| Autenticação | atacante não autenticado. A vítima precisa abrir (ou recarregar) uma URL. |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1 |
Fazer um usuário autenticado abrir uma URL com hash contendo parâmetros de fragmento de convidado. O cliente o desconecta, apaga a criptografia local e pode colocá-lo em um convidado do atacante. Isso é logout e apagamento de criptografia. Não é roubo do token real. Não é RCE no SO.
| Privilégio | Método / sink | Recon / integridade / disponibilidade | Comprovado em lab ou inferido |
|---|---|---|---|
| Analisar credenciais de convidado do hash | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | Integridade da seleção de sessão | Comprovado em lab. #/home?guest_user_id=...&guest_access_token=... tornou-se guest_params. Apenas query-string não. |
| Preferir convidado em vez de uma sessão armazenada não-convidado | Ramo guest-first de Lifecycle.loadSession, log Using guest access credentials | Integridade | Comprovado em lab. O @victim:example.org semeado não foi restaurado. |
| Apagar localStorage, conta IndexedDB, sessionStorage, criptografia | doSetLoggedIn(..., clearStorageEnabled=true) e então clearStorage() | Integridade / disponibilidade da sessão local | Comprovado em lab. crypto_empty=yes, token anterior sumiu. |
| Pular validação de token | O caminho de convidado nunca chama /_matrix/client/v3/account/whoami | Integridade | Comprovado em lab. whoami_called=no. Token inválido not-a-real-token ainda apagou. |
| Persistir credenciais de convidado do atacante | persistCredentials após o apagamento | Integridade | Comprovado em lab. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Fixar em um convidado real no HS padrão | Mesmo persist se o token de convidado for válido | Integridade | Inferido. O lab usou um token inválido, então sem login em HS ativo. |
| Continuar fazendo isso ao recarregar | As chaves de convidado permanecem no hash; onTokenLoginCompleted não as remove | Integridade | Inferido a partir do pin app.tsx. O lab abriu a URL uma vez. |
Descartado neste leftover: roubar o token de acesso real (ele é excluído, não exfiltrado). RCE / LPE no SO (Desktop nodeIntegration: false, sandbox). SPA do Element ativo (how=gadget). Query-string ?guest_user_id= (apenas fragmento). disable_guests: true mantém a sessão não-convidado. Um loadSession corrigido que ignora convidado quando existe uma sessão não-convidado também a mantém.
Outros leftovers do mesmo pin: vector: Windows drive-letter, Univention ICS javascript: href.
Fiz o pin do Element Web v1.12.29 após o release do GitHub de 22 de setembro de 2026. O loginToken do SSO é apenas query e removido após o uso. As chaves de convidado ainda ficam no fragmento e vencem sobre o restore. O comentário em url_utils.ts é a pista: eles já duvidavam que essas chaves fossem especificadas.
Caminhos errados já registrados: tratar o query-string ?guest_user_id= como o vetor (as chaves ficam no hash); chamar isso de roubo de token (o token real é excluído, não enviado); esperar disable_guests na config do app.element.io (não está definido). Um reverse shell. Teatro.
Gadget das funções do pin. Não é um contêiner do Element Web ativo. how=gadget.
python3 element-fragment-guest-Abraxas-Labs.py
ou
cd lab
./run.sh
Alvo apenas http://127.0.0.1:19600. Projeto Compose element-fragment-guest. A stack é desmontada após a execução.
SUCCESS element-fragment-guest how=gadget guest-wipe=yes prior-kept=no garbage-token=yes disable-guests-keeps=yes ELEMENT-FRAGMENT-GUEST-WITNESS
Ignorar parâmetros de fragmento de convidado quando já existe uma sessão não-convidado. Validar o token de convidado com /_matrix/client/v3/account/whoami antes de clearStorage. Remover guest_user_id e guest_access_token da mesma forma que os tokens SSO são removidos. Definir disable_guests: true por padrão para o app.element.io hospedado.
Lifecycle.ts (loadSession guest-first)url_utils.tsapp.tsx (enableGuest={!config.disable_guests})GNU Affero GPL v3.0. Veja LICENSE. Apenas lab em loopback. Sem garantia.