
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
Análise: https://abraxaslabs.tech/research/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. Os convidados estão ativados por padrão (enableGuest={!config.disable_guests}). O config.json de app.element.io não define disable_guests. onTokenLoginCompleted remove apenas os 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. Mesmo assim, eles prevalecem.
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 | ainda sem 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 |
| Produto | Element Web |
| Afetado | tag v1.12.29 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 |
| Laboratório | 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 deixá-lo em uma sessão de convidado controlada pelo atacante. Isso é logout e apagamento de criptografia. Não é roubo do token real. Não é RCE no SO.
| Privilégio | Método / sink | Reconhecimento / integridade / disponibilidade | Comprovado em laboratório ou inferido |
|---|---|---|---|
| Analisar credenciais de convidado a partir do hash | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | Integridade da seleção de sessão | Comprovado em laboratório. #/home?guest_user_id=...&guest_access_token=... tornou-se guest_params. Apenas na query string não funcionou. |
| Preferir convidado em vez de uma sessão armazenada de não convidado | Ramo guest-first de Lifecycle.loadSession, log Using guest access credentials | Integridade | Comprovado em laboratório. A sessão semeada @victim:example.org não foi restaurada. |
| Apagar localStorage, conta IndexedDB, sessionStorage, criptografia | doSetLoggedIn(..., clearStorageEnabled=true) e depois clearStorage() | Integridade / disponibilidade da sessão local | Comprovado em laboratório. crypto_empty=yes, token anterior removido. |
| Ignorar a validação de token | O caminho de convidado nunca chama /_matrix/client/v3/account/whoami | Integridade | Comprovado em laboratório. whoami_called=no. O token inválido not-a-real-token ainda apagou os dados. |
| Persistir credenciais de convidado do atacante | persistCredentials após o apagamento | Integridade | Comprovado em laboratório. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Fixar em um convidado real no HS padrão | Mesma persistência se o token de convidado for válido | Integridade | Inferido. O laboratório usou um token inválido, portanto não houve login em HS ativo. |
| Continuar fazendo isso ao recarregar | As chaves de convidado permanecem no hash; onTokenLoginCompleted não as exclui | Integridade | Inferido a partir do pin app.tsx. O laboratório abriu a URL uma vez. |
Fechado sobre este resíduo: roubar o token de acesso real (ele é excluído, não exfiltrado). RCE / LPE no SO (Desktop nodeIntegration: false, sandbox). SPA do Element ao vivo (how=gadget). Query-string ?guest_user_id= (apenas fragmento). disable_guests: true mantém a sessão não-convidada. Um loadSession corrigido que ignora o convidado quando existe uma sessão não-convidada também a mantém.
Mesmos resíduos de pin: vector: letra de unidade do Windows, Univention ICS javascript: href.
Fixe o Element Web v1.12.29 após o lançamento no GitHub de 22 de setembro de 2026. O loginToken do SSO é apenas de query e é removido após o uso. As chaves de convidado ainda ficam no fragmento e prevalecem sobre a restauração. O comentário em url_utils.ts é a pista: eles já duvidavam que essas chaves fossem especificadas.
Caminhos errados já registrados: tratar a 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 configuração do app.element.io (não está definido). Um reverse shell. Teatro.
Gadget das funções de pin. Não é um contêiner do Element Web ao vivo. how=gadget.
python3 element-fragment-guest-Abraxas-Labs.py
ou
cd lab
./run.sh
Aponte apenas para http://127.0.0.1:19600. Projeto do 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 os 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 como padrão para o app.element.io hospedado.
Lifecycle.ts (loadSession com prioridade para convidado)url_utils.tsapp.tsx (enableGuest={!config.disable_guests})GNU Affero GPL v3.0. Consulte LICENSE. Apenas laboratório em loopback. Sem garantias.