CVE 状态: 已请求,待分配。此发现已发布为 GHSA-g9vc-5j77-f2cm。在分配 CVE 后,此仓库将重命名为
CVE-YYYY-NNNNN-linux-entra-sso-PoC,并且此横幅将替换为 CVE 链接。
| 研究员 | Dostxodjayev Abdullox (@squeeze440) |
| 安全公告 | GHSA-g9vc-5j77-f2cm |
| CVSS 3.1 | 5.3(中危) |
| 弱点 | CWE-346, CWE-20 |
linux-entra-sso 中的 Platform.SSO_URL 缺少尾部路径分隔符,因此 Firefox/Thunderbird 的 onBeforeSendHeaders 防护(e.url.startsWith(Platform.SSO_URL))会被任何形如 login.microsoftonline.com.<attacker-domain> 的攻击者注册域名绕过,导致该扩展获取并将有效的 Entra ID 主刷新令牌(PRT)SSO cookie 注入到发送至攻击者自己主机的请求中。
siemens/linux-entra-sso — 用于 Linux 的浏览器插件,通过本地 Microsoft Identity Broker(Intune)在 Microsoft Entra ID 上实现 SSO。Firefox 构建版本实际上可被利用;Thunderbird 共享相同的易受攻击代码路径,但目前无法通过此向量触达(见详情);Chrome/Chromium 不受影响(见详情)。
v1.10.0(提交 676854c,截至 2026-08-03 的当前 main)。确认存在于当前发布版本中,即未被 GHSA-52rj-42vh-2rxc / CVE-2026-42177 修复(该修复仅涉及 Chrome 的 declarativeNetRequest 适配器)。
5.3(中危) — CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
AC:H — 利用需要该扩展持有已授予的主机权限,且该权限覆盖攻击者构造的主机名。实际上,攻击者必须通过社会工程学诱使受害者在攻击者页面上点击扩展的“Background SSO (enable)”链接——这一条件不在攻击者的直接控制范围内,与同类 GHSA-52rj-42vh-2rxc 所使用的复杂性理由一致。UI:R — 权限授予需要用户显式点击。C:H — 窃取的 PRT SSO cookie 可直接对 login.microsoftonline.com 重放,为受害者已同意的任何应用铸造访问/ID 令牌(完整的 SSO 会话劫持)。I:N/A:N — 该漏洞泄露凭据,但本身不修改数据或可用性。根本原因 — src/platform.js:9:
static SSO_URL = "https://login.microsoftonline.com";
没有尾部 /。
易受攻击的检查 — platform/firefox/js/platform-firefox.js:55-59:
async #onBeforeSendHeaders(e) {
// filter out requests that are not part of the OAuth2.0 flow
if (!e.url.startsWith(Platform.SSO_URL)) {
return { requestHeaders: e.requestHeaders };
}
...
String.prototype.startsWith 执行的是原始字符前缀比较,而非主机名/源比较。由于 Platform.SSO_URL 没有尾部路径分隔符,任何主机为 login.microsoftonline.com.<anything> 的 URL——一个攻击者完全控制的语法有效 DNS 名称——也会满足该检查,例如:
"https://login.microsoftonline.com.attacker.example/phish".startsWith("https://login.microsoftonline.com")
=> true
这正是 GHSA-52rj-42vh-2rxc 自身描述所称的“规范防御性检查……在 Chrome 适配器中缺失”的同一防御性检查——它在这里存在,但本身可被绕过,因此该公告的修复(仅加固了 Chrome 的 declarativeNetRequest 规则)使此路径保持开放。platform/thunderbird/js/platform-thunderbird.js 继承 PlatformFirefox 而未覆盖 update_request_handlers() 或 #onBeforeSendHeaders,因此 Thunderbird 继承了相同的缺陷。
触发路径(update_request_handlers,platform/firefox/js/platform-firefox.js:36-53): 监听器以 urls: this.well_known_app_filters 注册,该值由 chrome.permissions.getAll().origins 填充(src/platform.js:78-79,update_host_permissions())。用户已授予的任何主机权限——包括通过弹出菜单的“Background SSO (enable)”链接授予的单站点权限(popup/menu.js:171-260,使用从活动标签页派生的 current_filter = "https://" + tab_hostname + "/*")——就足以为该确切主机注册监听器。与 GHSA-52rj-42vh-2rxc 中描述的利用前提不同,不需要包罗万象的 https://*/* 权限;此处仅需对攻击者自己的仿冒域名进行一次针对性授予,这比先前公告的 PoC 门槛更低。
汇聚点 — 同一文件,第 60-70 行:
let prt = await this.#broker.acquirePrtSsoCookie(this.account, e.url);
ssoLog("inject PRT SSO into request headers");
e.requestHeaders.push({ name: prt.cookieName, value: prt.cookieContent });
e.url(完整的攻击者 URL)被直接作为 ssoUrl 传递给原生 broker。linux-entra-sso.py:27-30 记录 Microsoft broker 后端不会在服务端验证 ssoUrl(“正确的值不会被……授权后端检查”),因此无论怎样都会签发 cookie,并且它被注入到实际发往攻击者自己主机的请求头中——这是直接的数据外泄,而不仅仅是在发往 Microsoft 的请求上设置请求头。
Chrome 不受影响: platform/chrome/js/platform-chrome.js:96-99(GHSA-52rj-42vh-2rxc 修复后,提交 8183759)使用 "|" + Platform.SSO_URL + "/" 进行锚定(字符串起始锚点 + 尾部斜杠),并添加了显式的 requestDomains: [URL.parse(Platform.SSO_URL).hostname] 允许列表——两者都能正确拒绝 login.microsoftonline.com.attacker.example 主机。
Thunderbird — 相同的易受攻击代码,但目前无法通过此向量触达: platform/thunderbird/js/platform-thunderbird.js 未加修改地继承 PlatformFirefox,因此 Thunderbird 构建版本的二进制文件中存在相同的 startsWith 绕过。然而 platform/thunderbird/manifest.json 仅声明了固定的 "host_permissions": ["https://login.microsoftonline.com/*"],且没有 optional_host_permissions 键。WebExtensions 仅允许 chrome.permissions.request() 授予在 optional_permissions/optional_host_permissions 中预先声明的源;由于 Thunderbird 未声明任何此类源,弹出菜单的“Background SSO (enable)”流程(popup/menu.js:259-261)目前无法在 Thunderbird 上获取攻击者所选域名的权限。该缺陷在那里处于潜伏状态,目前攻击者无法触达,但仍应修复以实现纵深防御/以防该清单将来添加 optional_host_permissions。
针对真实发布的常量(直接从目标的 src/platform.js 导入,而非手工复制)动态确认了易受攻击的谓词。脚本保存在 ~/engagements/linux-entra-sso/evidence/prt_bypass_poc.mjs。
$ node prt_bypass_poc.mjs
Real Platform.SSO_URL from src/platform.js: "https://login.microsoftonline.com"
Legit MS URL passes filter (expected true): true
Attacker domain-suffix URL: https://login.microsoftonline.com.attacker.example/phish
Attacker URL passes filter (SHOULD be false, is): true
[CONFIRMED] Platform.SSO_URL lacks a trailing '/', so startsWith()
treats 'login.microsoftonline.com.attacker.example' as an in-scope
SSO endpoint. onBeforeSendHeaders would call:
broker.acquirePrtSsoCookie(this.account, "https://login.microsoftonline.com.attacker.example/phish")
and inject the returned PRT cookie into the request headers sent to
the attacker-controlled host.
链条的其余部分(broker 为未验证的 ssoUrl 签发 cookie,以及 WebExtensions webRequest 监听器为已授予的单主机权限触发)是静态追踪的,而非动态确认的——端到端复现它需要一台已注册的 Linux 主机,运行 microsoft-identity-broker 并连接真实的 Entra 租户,这超出了本环境范围。追踪的步骤如下:
login.microsoftonline.com.attacker.example 并在那里提供页面。popup/menu.js:259-261 → request_host_permission(["https://login.microsoftonline.com.attacker.example/*"]))。chrome.permissions.onAdded → on_permissions_changed()(src/background.js:30-34)→ update_host_permissions() 刷新 well_known_app_filters → update_request_handlers() 重新注册 Firefox 的 webRequest.onBeforeSendHeaders 监听器,包含新的主机模式。https://login.microsoftonline.com.attacker.example/... 的 main_frame/sub_frame 请求触发监听器;startsWith 检查(如上所示被绕过)通过。broker.acquirePrtSsoCookie(account, e.url) 返回真实的 PRT cookie(根据 linux-entra-sso.py:27-30,ssoUrl 未被 broker 后端验证)。攻击者若能让 linux-entra-sso 的 Firefox 用户为一个攻击者控制的仿冒域名授予“Background SSO”,就会直接在自己的服务器上收到受害者的 Entra ID PRT SSO cookie。该 cookie 可对 login.microsoftonline.com 重放,以获取受害者已同意的任何应用程序的访问/ID 令牌——完整的 SSO 会话劫持。与先前的公告不同,这不需要宽泛的 https://*/* 包罗万象权限,只需在攻击者自己的域名上进行单站点授予。Thunderbird 附带相同的缺陷检查,但其清单目前无法在运行时授予任意域名权限,因此今天无法通过此向量利用(见详情)。
将比较锚定到正确的源/主机名检查,而非原始字符串前缀,与已应用于 Chrome 适配器的修复保持一致:
if (!e.url.startsWith(Platform.SSO_URL + "/")) {
return { requestHeaders: e.requestHeaders };
}
或者更稳健地,将 new URL(e.url).origin 与 new URL(Platform.SSO_URL).origin 进行比较(也能拒绝 userinfo/端口技巧)。在 Platform.SSO_URL 常量层面应用修复(在 src/platform.js 中一次性添加尾部 /)将为 Firefox 检查及该常量的任何其他使用者关闭此问题,而一个断言 startsWith 拒绝 https://login.microsoftonline.com.attacker.example/... 的回归测试将弥补覆盖缺口,正如 Chrome 修复所建议的 testMatchOutcome 回归测试为 GHSA-52rj-42vh-2rxc 所做的那样。
Dostxodjayev Abdullox(GitHub:squeeze440)
仓库中不存在 SECURITY.md,且 GitHub API 报告没有仓库级安全策略,但 siemens/linux-entra-sso 已启用 GitHub 私有漏洞报告(通过该仓库 Security 标签页的“Report a vulnerability”按钮验证)。请通过该渠道报告:https://github.com/siemens/linux-entra-sso/security/advisories/new。