Firefox的CVE-2026-8971漏洞

admin 2026-06-24 05:28:30 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2026-8971是FirefoxJAR组件中第三次出现的同源策略绕过漏洞,攻击者通过URL路径中嵌入空字节实现文件名欺骗和MIME类型混淆。该漏洞允许恶意页面利用扩展的webaccessibleresources重定向信任边界,导致浏览器错误归属资源来源。Mozilla在五天内修复漏洞,根本教训在于需在输入解析层全局拒绝空字节而非仅修补下游消费者。 综合评分: 87 文章分类: 漏洞分析,WEB安全,安全建设,实战经验,渗透测试


起点

我并非特意寻找此漏洞。在 Mozilla 发布了禁止对 JAR 通道进行内容嗅探的修复后,我重新审视了该漏洞链中的第二个漏洞 CVE-2026-2790。我想确认这个修复是否真的关闭了我用双编码空字节技巧打开的那扇门。

我当时的假设很窄:检查禁用嗅探是否也阻止了文件名层面的技巧,还是仅仅阻止了脚本执行路径。在浏览器中,嗅探和文件名解析是不同的代码路径,关闭其中一个的补丁很少能意外地关闭另一个。我原本期望发现嗅探被干净利落地禁用,而攻击面上的其他部分保持不变。

我是对的,但方式出乎意料。该修复确实抵御住了前一个漏洞中使用的精确双编码技术。但当我回归基础,在 jar: 路径中直接尝试一个单一的、非双编码的 %00,并针对前两个补丁尚未触及的 URL 部分进行测试时,它依然奏效。

追踪

我这次的方法刻意显得平淡无奇。我没有发明新技术,而是回顾了前两个漏洞没有明确测试过的空字节放置的每一种变体,并逐一在全新的、打好所有补丁的 Nightly 版本上进行测试。

我用 Python 的一个小程序,利用标准的 zipfile 模块构建测试归档,没什么花哨的,只是在 test.zip 中放了几个名为 image.jpg 和 style.css 的虚拟条目。然后我直接在 Firefox 地址栏中输入:尝试带有原始 %00 的 jar:file:/// 路径,但将空字节放在条目路径的不同位置,而不是文件实际的归档条目名称中。这个区别很重要。

第一个漏洞将空字节放在 JAR 条目名称本身。第二个漏洞将其放在同一条目名称的双编码形式中。我想知道,如果空字节位于 !/ 分隔符之后的路径段中,而之前的两个修复都未曾触及这部分,会发生什么。

早期信号很快出现。导航到 jar:file:///path/to/archive.zip!/%00://evil.exe 会弹出一个下载提示,而 Firefox 建议保存的文件名是 evil.exe,完全由攻击者选定,无论归档内的实际内容是什么。这告诉我,下载文件名逻辑仍然信任空字节之后的任何内容,完全独立于内容嗅探的修复。

接着我直接瞄准了 MIME 解析。像 jar:file:///C:/Users/<user>/Desktop/test.zip!/%00style.css.html 这样的 URL,被以 text/html 的类型提供。一个以 .xml 结尾的变体会触发 Firefox 自身的 XML 解析错误页面,这实际上是整个调查中最有用的负面结果,因为它证明了 Firefox 是根据空字节之后的内容扩展名,而不是根据真实文件来推导内容类型的。

CVE-2026-2790 的嗅探修复正如设计那样正常工作。它只是并非空字节能引发此问题的唯一地方。

我还检查了 resource:///,因为根据第一个漏洞的讨论串,我记得 Mozilla 的 Rob Wu 指出它在内部会解析到 jar: URL。结果相同:resource:///%00.html 和 resource:///%00test/ 都显示出相同的空字节泄漏。这比看起来更重要,因为 resource:/// 是 moz-extension:// 内部解析到的协议,而当扩展在 web_accessible_resources 中暴露通配符条目时,moz-extension:// 可以被普通的网页内容访问。

一个页面运行 window.location = "moz-extension://<uuid>/logo.png%00://update.exe",就可以将一个合法的、已安装的扩展,变成一个名为 update.exe 的文件的表面来源。

挑战

第一个挑战是说服自己,这不是 CVE-2026-2790 换了种方式的旧戏重演。我花了相当多的时间重新阅读我自己旧的漏洞报告和嗅探修复的补丁说明,才确信我这次看到的是一个真正不同的代码路径。看到一个空字节做了意想不到的事情,就很容易假设自己重新发现了之前的漏洞。

我必须将文件名欺骗行为与 MIME 混淆行为分离开来,并独立证明每一种行为,这意味着要为每一种行为构建独立的最小化测试用例,而不是用一个可能被解释为与旧漏洞重叠的组合证明来糊弄。

第二个挑战是 moz-extension 的角度。我可以很容易地复现 resource:/// 的行为,但要证明它能从实际的网页内容中触及,而不仅仅是靠我在地址栏中输入触发,则花了更长时间。

在 Firefox 的安全模型中,地址栏导航和远程触发的待遇截然不同,一个只能在用户手动粘贴精心构造的 URL 时才起作用的漏洞,比恶意页面能自行触发的漏洞,其发现价值要弱得多。我借鉴了 CVE-2025-1936 的先例,因为 Rob Wu 在那次早期的披露中已经详细阐述了通配符 web_accessible_resources 的角度,我不需要从头再探索一遍。

整个过程背后还有一种更深沉的沮丧感。我已经两次走过分类处理流程。我知道 Mozilla 会问与第一个漏洞相同的根本原因问题:这真的可以被利用吗,还是只是一个没人能触及的内部协议怪癖?

我在提交报告之前就花时间完善了描述,试图预先阻止那些来回的辩论,因为我深知要绕过它需要多久。

突破

顿悟时刻是认识到,之前的两个修复都把空字节当作一个需要在特定函数解决的具体问题,而不是把它当成一个一开始就不应被视为有效输入的输入。CVE-2025-1936 的修复将 JAR 条目处理代码中的 char* 和 strlen 换成了 nsACString,这阻止了空字节在该特定位置静默截断字符串。CVE-2026-2790 的修复完全关闭了对 JAR 通道的内容嗅探,从而阻止了通过双编码技巧执行脚本。

每个修复都关闭了上一个漏洞穿过的确切那扇门,而每次空字节都干脆使用了另一扇门。正是这一点使它成为一次对绕过的绕过,而不是两个无关的漏洞。根本缺陷自始至终都是一样的。

一旦我清晰地将其隔离出来,根本原因就很简单:在 Firefox 解析 jar: 或 resource:/// URL 时,没有任何地方拒绝一个嵌入的 %00。迄今为止的每一次修复,都是在空字节造成可见损害的那个具体点上打的补丁。文件名解析逻辑和 MIME 类型推导逻辑是另外两个这样的点,之前未打补丁,而且不能保证它们是最后两个。

从概念上讲,利用条件可以分为两种情况。对于本地文件向量,攻击者需要受害者打开一个指向攻击者控制路径的归档的、经过精心构造的 jar:file:/// URL,这会导致下载文件名被欺骗,出现攻击者选择的扩展名,而无论归档的实际内容是什么。对于可被网页访问的向量,攻击者需要一个在 web_accessible_resources 中暴露通配符条目的目标浏览器扩展,因为正是这一点使得 moz-extension:// 到 resource:/// 再到 jar: 的链条可以从普通网页访问,而不仅限于手动地址栏输入。

在第二种情况下,任何页面上的脚本都可以将浏览器重定向到属于某个已安装扩展的 moz-extension:// URL,附加一个空字节和一个虚假文件名,让 Firefox 呈现一个表面看来源自该合法扩展的下载对话框。

用通俗的话说,其影响是诱使用户下载并运行他们认为无害的东西,同时由听起来合法的来源为攻击者完成社交工程。但 SOP 绕过的分类意义不仅限于标签。同源策略是一种机制,它防止来自一个信任边界内的页面或资源被当作属于另一个信任边界的东西来处理。

在这里,信任边界是扩展声明的 web_accessible_resources 表面,即扩展作者选择暴露给网页的明确、狭窄的路径集合。空字节让攻击者可以跨出这个声明的表面,而浏览器仍将响应归因于该扩展的源,因为对基于 jar: 的资源的来源归因会经过与空字节破坏的条目解析逻辑相同的流程。这不是沙箱逃逸,就其本身而言也不是远程代码执行。

这是一个起源归因失败,被武器化为信任操控的原始手段,这类漏洞通常成为更长漏洞链的第一步,而不是最终Payload。

披露与解决

| | | | — | — | | 报告日期 | 2026年4月16日,通过 Mozilla Bugzilla | | 补丁落地 | 2026年4月21日 | | 奖金发放 | 2026年4月22日 | | 修复版本 | Firefox 151 | | 分配的CVE | CVE-2026-8971 | | 公开披露 | 2026年5月19日,通过 MFSA2026-46 |

在我报告漏洞五天之后,修复就落地了,这对于一个需要交叉引用两个先前 CVE 才能正确评估的漏洞来说,是一个非常快的响应速度。这次分类处理明显比我在这系列中的第一次报告要顺利。到了已知链路中的第三个漏洞,团队已经有了相应的背景来快速行动,而这个背景确实带来了真正的不同。

实际的代码变更——在解析点检查 JAR 条目名称中是否嵌入空字节,而不是在下游——按照 Mozilla 自己的评估,是小范围且低风险的,这与一旦看清后,剩余漏洞实际上有多狭小是相符的。

防御者应吸取的教训

如果你正在审查自己的软件如何处理不受信任的路径或文件名,这里的模式值得内化:在发现漏洞的函数处应用的空字节修复,并不意味着输入已被拒绝,它只意味着该输入的一个消费者已被强化。如果相同的未清理值到达了第二个消费者,漏洞就会以不同的效果重新出现。

我建议的实际测试是:追踪 URL 解析器输出的所有百分号解码字符串的消耗位置,而不仅仅是你发现原始问题的地方。在这种情况下,这意味着 JAR 条目查找、内容嗅探逻辑、文件名解析代码和 MIME 类型推导代码都是同一个受污染字符串的独立消费者,在底层的输入验证缺口真正关闭之前,每一个都需要其独立的妥协措施。

另一个可迁移的要点是关于内部协议的别名映射。moz-extension:// 看起来像一个自包含的安全内部方案,掩盖了它只是 resource:/// 的一个薄层包装,而 resource:/// 本身又是 jar: 的一个薄层包装。任何时候,当某个内部方案在文档中被描述为在底层解析到另一个方案时,请假设底层方案中的漏洞同样适用于包装器,并明确地测试它们,而不是假设包装层会清理任何东西。

结束语

对于同一个字节的两次绕过告诉我,修复你看得见的症状,并不等同于拒绝了你本应拒绝的输入。我将用这个视角再回顾 Firefox 的其他内部协议处理器,因为 JAR 不太可能是唯一存在这种模式的地方。

原文:https://payatu.com/blog/bypass-of-bypass-in-mozilla-firefox-cve-2026-8971/

  • END –

感谢阅读,如果觉得还不错的话,动动手指给个三连吧~


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:骨哥说事 骨哥说事 骨哥说事《Firefox 的 CVE-2026-8971 漏洞》

cc 网络安全文章

cc

文章总结: 该文档内容显示为一条2026年6月23日来自河南的用户社交帖子,包含问候语阿乐你好及小说阅读相关提示(在小说阅读器读本章去阅读),但未提供具体技术内
评论:0   参与:  0