abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-fragment-guest
技术文章:https://abraxaslabs.tech/research/element-fragment-guest
Element Web v1.12.29 - Element / New Vector
类别: 会话销毁 可达性: 远程
Lifecycle.loadSession 优先使用 URL hash 中的 guest_user_id 和 guest_access_token,而不是 restoreSessionFromStorage。访客模式默认开启(enableGuest={!config.disable_guests})。app.element.io 的 config.json 未设置 disable_guests。onTokenLoginCompleted 只剥离 SSO 和 OIDC 参数,从不剥离访客密钥。url_utils.ts 中已有注释指出这些 fragment 参数看起来未被使用。但它们仍然生效。
任何能让已登录用户打开带有访客 fragment 参数的 hash URL 的人,都能使其登出并清除本地加密数据。一个无效令牌就足够了。whoami 从未被调用。
| ID | 暂无 CVE |
| CWE | CWE-384 / CWE-352 / CWE-613 |
| CVSS | 高危:7.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H |
| 产品 | Element Web |
| 受影响版本 | v1.12.29 标签 v1.12.29(2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e)。访客已启用(默认)。 |
| 认证 | 未认证攻击者。受害者必须打开(或重新加载)一个 URL。 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
让已登录用户打开带有访客 fragment 参数的 hash URL。客户端会使其登出、清除本地加密数据,并可能将其置于攻击者的访客会话中。这是登出和加密数据清除。这不是窃取真实令牌。这不是操作系统 RCE。
| 权限 | 方法 / 汇聚点 | 侦察 / 完整性 / 可用性 | 实验验证或推断 |
|---|---|---|---|
| 从 hash 解析访客凭据 | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | 会话选择的完整性 | 实验验证。#/home?guest_user_id=...&guest_access_token=... 变成了 guest_params。仅查询字符串则不会。 |
| 优先使用访客而非已存储的非访客会话 | Lifecycle.loadSession 访客优先分支,日志 Using guest access credentials | 完整性 | 实验验证。预置的 @victim:example.org 未被恢复。 |
| 清除 localStorage、IndexedDB 账户、sessionStorage、加密数据 | doSetLoggedIn(..., clearStorageEnabled=true) 然后 clearStorage() | 本地会话的完整性 / 可用性 | 实验验证。crypto_empty=yes,先前的令牌已消失。 |
| 跳过令牌验证 | 访客路径从不调用 /_matrix/client/v3/account/whoami | 完整性 | 实验验证。whoami_called=no。无效令牌 not-a-real-token 仍然触发了清除。 |
| 持久化攻击者的访客凭据 | 清除后执行 persistCredentials | 完整性 | 实验验证。after_user=@x:example.org、after_token=not-a-real-token、mx_is_guest=true。 |
| 在默认 HS 上固定到真实访客 | 若访客令牌有效,则同样持久化 | 完整性 | 推断。实验使用了无效令牌,因此没有实时 HS 登录。 |
| 重新加载时持续生效 | 访客密钥保留在 hash 中;onTokenLoginCompleted 不会删除它们 | 完整性 | 根据固定版本 app.tsx 推断。实验仅打开该 URL 一次。 |
收尾了这条遗留问题:窃取真实访问令牌(它被删除,而非被外泄)。操作系统 RCE / LPE(桌面端 nodeIntegration: false,沙箱)。实时 Element SPA(how=gadget)。查询字符串 ?guest_user_id=(仅限片段)。disable_guests: true 会保留非访客会话。一个打过补丁的 loadSession,在存在非访客会话时忽略访客,同样会保留它。
同样的 pin 遗留问题:vector: Windows 盘符、Univention ICS javascript: href。
在 2026 年 9 月 22 日的 GitHub 发布之后,我 pin 了 Element Web v1.12.29。SSO loginToken 仅限查询字符串,并在使用后被剥离。访客密钥仍留在片段中,并优先于恢复。url_utils.ts 中的注释就是线索:他们本就怀疑这些密钥未被规范定义。
已记录的弯路:把查询字符串 ?guest_user_id= 当作向量(密钥位于哈希中);称此为令牌窃取(真实令牌被删除,而非发送);期望 app.element.io 配置上有 disable_guests(它未设置)。一个反向 shell。戏剧。
pin 函数的 gadget。不是实时 Element Web 容器。how=gadget。
python3 element-fragment-guest-Abraxas-Labs.py
或
cd lab
./run.sh
仅针对 http://127.0.0.1:19600。组合项目 element-fragment-guest。运行结束后栈会被拆除。
SUCCESS element-fragment-guest how=gadget guest-wipe=yes prior-kept=no garbage-token=yes disable-guests-keeps=yes ELEMENT-FRAGMENT-GUEST-WITNESS
当已存在非访客会话时,忽略访客片段参数。在 clearStorage 之前,通过 /_matrix/client/v3/account/whoami 验证访客令牌。像剥离 SSO 令牌那样,剥离 guest_user_id 和 guest_access_token。对于托管的 app.element.io,默认设置 disable_guests: true。
Lifecycle.ts(loadSession 访客优先)url_utils.tsapp.tsx(enableGuest={!config.disable_guests})GNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。不提供任何担保。