本目录包含一个用于如实复现 Firefox WebRender 中 Fission 站点隔离授权绕过的脚手架。在 Fission 下,每个内容进程拥有独立的 PipelineId 命名空间,但负责注册可合成 PipelineId 的 GPU 进程代码从未检查该 PipelineId 的命名空间是否属于发送进程。因此,一个已被攻陷的内容进程可以在另一个进程的命名空间中注册 PipelineId,并在共享管理器中覆盖该源的异步图像管线。
此处所有内容仅针对本地构建的 Firefox 代码树,且仅使用合成内容。它从不攻击、联系、探测或引用任何在线或第三方系统。它不是远程代码执行,也不是内存破坏;威胁模型是一个已被攻陷的内容进程。
匹配的 PoC 仓库:https://github.com/defineid/Trespasser
技术说明:本作品集中的 writeup-webrender-pipelineid.html。
| 字段 | 值 |
|---|---|
| CVE | CVE-2026-74970 |
| 组件 | Core / Graphics: WebRender |
| 类别 | 站点隔离绕过 |
| CWE | 862(缺少授权)· 284(访问控制不当) |
| 修复于 | Firefox 154 · ESR 153.1 |
| Bug | https://bugzilla.mozilla.org/show_bug.cgi?id=2056558 |
| PoC 仓库 | https://github.com/defineid/Trespasser |
在 Fission 下,WebRender 为每个内容进程分配独立的 PipelineId 命名空间。GPU 进程桥接层应当拒绝任何命名空间不属于发送进程的资源,从而确保一个内容进程无法寻址或覆盖另一个内容进程的渲染资源。
WebRenderBridgeParent::AddPipelineIdForCompositable 运行在 GPU 进程中,它会针对根/WebRender 守卫以及该桥接层自身已注册的管线集合来验证传入的管线,但从未对 PipelineId 调用 MatchesNamespace。同一文件中的 image-key、font-key 和 blob-key 路径都会执行该 MatchesNamespace 所有权检查;而 PipelineId 路径则完全没有执行。RemovePipelineIdForCompositable 同样未做检查,因此移除路径上也存在相同的命名空间所有权漏洞。
在下游,AsyncImagePipelineManager::AddAsyncImagePipeline 仅用 MOZ_ASSERT 来保证管线的唯一性,而该断言在发布版本中会被编译为空操作。因此,当一个伪造的跨命名空间 PipelineId 到达共享的 AsyncImagePipelineManager 时,管理器不会拒绝该重复项:它会静默覆盖受害源已有的异步图像管线条目。
将上述环节串联起来,一个已被攻陷的内容进程 A 可以伪造一个命名空间属于内容进程 B(在 Fission 下为不同源、位于独立进程)的 PipelineId,在可合成注册路径上提交它,并让 GPU 进程接受它,从而在共享管理器中覆盖 B 的图像管线。
Fission 下已被攻陷的内容进程。假设攻击者已在一个内容进程中拥有代码执行能力(例如通过另一个内容进程漏洞),并且能够发送带有攻击者所选字段的 WebRender IPC 消息。该缺陷正是缺失的授权检查,使得该进程能够跨越站点隔离边界,触及另一个源的渲染资源。
这是一个 Fission 站点隔离授权绕过,而非内存破坏。其影响是跨源渲染混淆和跨标签页拒绝服务。下游消费者均受空值保护并采用引用计数,因此不会导致代码执行。PoC 不得且并未声称可实现代码执行。
README.md — 本文件。forge-namespace.patch — 一个用于本地 Firefox 源码树的研究补丁。在内容侧,它由 XRE_IsContentProcess() 和环境变量 MOZ_POC_FORGE_WR_NAMESPACE 保护,伪造出站 PipelineId 的命名空间。在 GPU 进程父侧,当注册了跨命名空间的 PipelineId 时,它会打印一条 ACCEPTED 诊断信息,证明缺失的检查让其通过了。poc.html — 一个纯内容侧测试用例:一个 WebGL 画布(因此会创建一个异步图像管线)加上一个跨源进程外 iframe(因此 Fission 会将其放入单独的内容进程)。在未修改的构建上,它正常渲染,没有任何可观察的行为。victim.html — iframe 加载的合成第二源。它是一个简单的、无脚本的页面,唯一作用就是作为一个活跃的跨源文档,以便在 Fission 下落入其自己的内容进程,拥有自己的 PipelineId 命名空间(伪造注册所针对的命名空间)。poc-render.png — 在本地未修改的 Firefox 140.11.0esr 中加载 poc.html 的截图。它显示测试页面正常渲染:WebGL 画布绘制其帧,进程外 iframe 加载 victim.html。它仅显示良性渲染。绕过本身需要研究补丁和存在漏洞的构建,且在此处未被触发(见验证状态)。这些步骤旨在由作者针对本地 Firefox 检出执行。在此环境中,没有任何内容针对 Firefox 执行过(见下方验证状态)。
检出一个存在漏洞的 Firefox 源码树(154 之前 / ESR 153.1 之前),并确认 Fission 已启用(fission.autostart = true,近期构建的默认值)。
从源码树顶部应用研究补丁:
patch -p1 < forge-namespace.patch
该补丁涉及 gfx/layers/wr/WebRenderBridgeChild.cpp(内容侧,伪造命名空间)和 gfx/layers/wr/WebRenderBridgeParent.cpp(GPU 进程侧,打印 ACCEPTED 诊断信息)。除非满足防护条件,否则这两处更改均不生效。
正常构建(./mach build)。
提供此目录的服务,使 poc.html 的进程外 iframe 从真正不同的可注册域加载配套的 victim.html,从而让 Fission 将 iframe 放入其独立的内容进程。例如,python3 -m http.server 8000 --bind :: 并从 http://victim.localtest.me:8000/victim.html 加载 iframe。参见 poc.html 中的内联注释。
使用已设置的伪造变量启动构建并加载测试页面:
MOZ_POC_FORGE_WR_NAMESPACE=999999 ./mach run --temp-profile poc.html
999999 是一个任意选取的命名空间值,其目的是确保它不属于任何真实进程;它能让伪造的跨命名空间注册在日志中一目了然。
在应用补丁后的存在漏洞的构建上,GPU 进程的父进程会接受并注册一个 PipelineId,而该 PipelineId 所属的命名空间并不属于任何此类进程,并打印出(这是撰写报告中所展示的确切形式):
[POC-2056558] ACCEPTED cross-namespace PipelineId:
sender-namespace=4 pipeline-namespace=999999 (should have been rejected)
sender-namespace 是发送内容进程合法拥有的命名空间;pipeline-namespace 是伪造的值。这两个不同的值,再加上注册被接受这一事实,正是问题的关键所在:本应拒绝它的所有权检查缺失了。
在修复后的构建(154 / ESR 153.1 及更高版本)中,同一条消息会被拒绝并返回 IPC_FAIL,且不会打印这样的 ACCEPTED 行,因为 PipelineId 路径现在会强制执行 MatchesNamespace。
在 PipelineId 路径上强制执行资源键路径已经在使用的同一命名空间所有权检查:
if (!MatchesNamespace(aPipelineId)) {
return IPC_FAIL(this, "PipelineId namespace does not belong to the sending process");
}
在 AddPipelineIdForCompositable 中应用(并在 RemovePipelineIdForCompositable 上对称应用),这会拒绝任何命名空间不属于发送进程的 PipelineId,从而关闭该绕过路径。
poc.html 在本地原版 Firefox 140.11.0esr 中加载了一次,并捕获为 poc-render.png;该截图仅显示测试页面正常渲染(WebGL 画布绘制一帧,进程外 iframe 加载 victim.html)。由于本地 Firefox 是原版、未打补丁的构建,截图中不包含伪造的注册,也不包含 [POC-2056558] 日志行。要捕获接受跨命名空间的输出,请将补丁应用到本地存在漏洞的构建,并按上述说明自行运行。此脚手架除演示缺失的授权检查会让跨命名空间 PipelineId 通过之外,不包含任何利用原语。它不尝试代码执行,也不产生内存破坏。
本内容针对本地构建的 Firefox 源码树,使用合成的、自行编写的内容,用于一份关于已报告、已修补 CVE 的报告。研究补丁受到保护,仅影响本地开发者构建,并编码了报告所描述的受损内容进程假设;它不是远程漏洞利用。此处没有任何内容攻击、联系、探测或引用攻击任何在线或第三方服务。测试用例中的进程外 iframe 是复现 Fission 进程拆分所固有的,并已如此记录;顶层页面本身没有其他网络依赖。