0关于WebAssembly
WebAssembly(Wasm)是一种新型的、可移植的、高效的二进制指令格式,可作为多种高级语言(如C、C++、Rust等)的编译目标,从而在Web上运行接近原生性能的应用程序。
在浏览器中,Javascript在虚拟机(VM)中执行,通过JIT优化代码以提升性能。尽管Javascript是当前最快的动态语⾔之一,但在性能上仍无法与原生的C和C++代码竞争。这正是 Wasm 的优势所在。Wasm运行在与Javascript相同的VM中,但性能更优。两者可以自由交互,互为补充,使开发者既能享受Javascript丰富的生态系统和友好的语法,又能获得Wasm接近原生的性能。
通常,开发者使用C等语言编写Wasm模块,并将其编译为.wasm文件。这些.wasm文件不能直接被浏览器识别,需要通过Javascript的胶水代码进行加载。
1越来越多的浏览器漏洞源自WebAssembly组件
Wasm作为现代Web应⽤的核心技术之一,通过沙箱化的执行机制,实现了接近原生的性能和安全性的双重保障,其应用范围已超越浏览器,快速渗透到云计算、物联网、边缘计算等关键领域。然而,随着Wasm的普及,其安全隐患也逐渐显现。
从厂商披露的漏洞来看,越来越多的漏洞源自Wasm组件。
Wasm的安全隐患已在多次攻防实战中得到验证。在Pwn2Own 2021大赛中,研究人员利用JavascriptCore引擎的Wasm编译器漏洞(CVE-2021-1801),在Safari浏览器上实现了远程代码执行(RCE)。在Pwn2Own 2023的V8 CT中,也有团队利用V8的Wasm相关漏洞成功攻破了Chrome浏览器。从各大厂商的漏洞跟踪平台上,也能看到越来越多的Wasm漏洞被披露。
自2017年11月Wasm社区组(CG)发布最小可行产品(MVP)标准以来,该技术栈始终处于动态演进状态。四大主流浏览器厂商(Chrome、Edge、Firefox、Safari)通过标准化进程持续推进特性扩展。截至目前,还有许多特性尚未完全支持,且Wasm标准也在不断更新。这些新特性的引入,势必会带来潜在的漏洞风险。因此,Wasm已成为当前浏览器漏洞挖掘的热点,并具有长期的研究价值。
云鼎实验室对Wasm的漏洞挖掘进行了深入的探索,成功挖掘了多个高危漏洞,提交了数十个漏洞报告,并获得了苹果公司(Safari)和Mozilla基金会(Firefox)的官方致谢。
2WebAssembly模糊测试实践
在2022至2024年的Black Hat大会上,连续出现了与Wasm安全相关的议题。这些研究均以模糊测试(Fuzzing)作为漏洞挖掘的主要手段。
云鼎实验室早期也曾尝试对Wasm进行模糊测试,但效果并不理想。后来,受BlackHat上相关议题的启发,云鼎实验室改写了Wasm Fuzzer,成功找到了新的漏洞。
改写后的Wasm Fuzzer工作流程如下:
1. 种子生成:从语料库中提取种子,并进行变异得到随机输入。
2. 生成器:将随机输入传递给生成器,映射成结构正确的Wasm模块。
3. JS模版嵌入:将生成的Wasm模块嵌入到预先准备好的JS模版中。
4. 执行与反馈:使用浏览器的JS引擎解释执行生成的JS样本,并回传覆盖率信息,形成反馈循环。
而这其中的关键技术点在于:
● 生成器的设计:Wasm模块是一个结构化的输入,因此Fuzzer的核心在于如何让生成器尽可能生成合法且多样化的样本。随着Wasm标准的更新以及新特性的引入,构建一个支持全面特性的高效生成器具有挑战性。
● JS模版的设计:精心设计的JS模版可以更有效地触发引擎的各种行为。例如,通过设计循环结构,增加热点代码的执行频率,从而触发不同层级的JIT编译器。
在研究现有工作后,云鼎实验室发现,Chrome V8为了方便内部测试,提供了构建Wasm的接口(API),利⽤这些接口,可以在较细粒度构建Wasm模块。这样一来,既降低了开发成本,又能紧跟V8对Wasm新特性的支持。
同时,云鼎实验室还设计了一些Javascript模版来触发JIT并捕获非崩溃错误。
很快,新改写的Fuzzer跑出了有意思的结果。
3新的漏洞:CVE-2025-1933
与纯Javascript一样,Wasm在浏览器中也有JIT。以Firefox为例,其JIT编译器有三个优化级别:baseline、Ion、Optimizing。简单来说,代码执行得越频繁,优化级别就越高。这意味着,同一个函数的首次执行和第1000次执行,生成的机器码可能完全不同,因为编译器可能发生了变化。
新的漏洞由此产生。
在一次函数调用过程中,一个经过Wasm-Ion编译的函数返回整数值3,该值被存储在栈中。对应的汇编代码如下:
函数返回后,在一个经过Wasm-baseline编译的函数中,希望将这个值从栈中弹出到rax寄存器。
然而,实际弹出的值是0x7ffd00000003,其中低32位是期望的值3 ,但高32位是未初始化的垃圾数据。这是因为被调用函数只存储了一个int32(32位整数),未正确清零高32位。接着,返回到JIT入口桩代码(JIT entry stub),程序执行了以下代码:
注释提到“无需扩展,因为值已被装箱”,这里是因为 boxNonDouble函数假设了输入寄存器中的高32位已被正确清零。但是如果高位存在垃圾数据,会导致装箱后的结果不正确,进而导致程序崩溃。
4漏洞如何发生?如何修复?
CVE-2025-1933漏洞产生的根本问题在于64位系统上没有对int32类型的值进行正确处理。
系统如果不正确处理高32位,可能导致高位残留垃圾数据。当返回值用于装箱(即转换为Javascript的Value类型)时,如果高位包含非零值,装箱结果可能错误,甚至被误解为其他数据类型。
具体而言,在GenerateJitEntry函数中,处理返回值时,没有对int32类型的返回值进行适当的扩展:
然而,boxNonDouble操作假设ReturnReg中的高位已清零。缺少适当的零扩展,导致高位包含垃圾数据,与类型标签进行或运算后,生成错误的Value。
该漏洞的安全影响较为严重,被评估为sec-high级别。攻击者可能利用该漏洞,通过精心构造的Wasm模块,利用堆喷等技术诱导引擎在返回值的高位留下可控的垃圾数据,进而实现类型混淆,导致任意代码执行。
补丁的修复方法简单直接。
在64位系统上,使用masm.widenInt32(ReturnReg);将int32值扩展为64位,确保高32位被正确清零,防止高位残留垃圾数据。Patch如下:
5大模型在Wasm Fuzzing中的应用
随着大模型(LLM)的兴起,基于LLM的模糊测试方法逐渐受到关注。理论上,LLM具备理解和生成代码的能力,可以辅助生成更智能的测试样本,覆盖更多的代码路径。
在Wasm Fuzzing领域,LLM可以用于:
● 智能生成样本:利用LLM理解Wasm模块的结构和语义,生成更具针对性的测试样本。
● 漏洞预测与分类:通过分析历史漏洞数据,训练模型预测可能存在漏洞的代码区域,提高测试效率。
● 辅助漏洞分析:在崩溃发生后,利用LLM辅助进行漏洞定位和根因分析,加速漏洞修复。
作为一项新兴技术,Wasm仍在快速发展中,也是现代浏览器的重要攻击面之一。新的特性和标准的引入,将为安全研究带来新的挑战和机遇。腾讯安全及云鼎实验室也将持续跟踪深入研究,助力企业组织及时发现安全风险,完善安全防线。
参考文献
1. Liu, S. Achilles Heel of JS Engines: Exploiting Modern Browsers During WASM Execution. Black Hat USA 2024.
BH-US-24/Presentations/US24-Liu-Achilles-Heel-of-JS-Engines-Exploiting-Modern-Browsers-During-WASM-Execution.pdf
2. Cao, Y. Attacking WebAssembly Compiler of WebKit. Black Hat Asia 2023.
Asia-23/AS-23-Cao-Attacking-WebAssembly-Compiler-of-Webkit.pdf
3. Ventuzelo, A. A Journey Into Fuzzing WebAssembly Virtual Machines. Black Hat USA 2022.
USA-22/Wednesday/US-22-Ventuzelo-A-Journey-Into-Fuzzing-WebAssembly-Virtual-Machines.pdf
4. WebAssembly Community Group. WebAssembly Features.
features/
5. Apple Inc. JavascriptCore. WebKit Source Code.
WebKit/WebKit/tree/main/Source/JavascriptCore
6. Google Inc. V8 Javascript Engine.
v8/v8
7. Mozilla Foundation. gecko-dev.
mozilla/gecko-dev
0 条