author: @relooadin / X
2024-06-03 17:09:52
Shout out to @buptsb and @mistymntncop for their brilliant work.

漏洞信息

Chrome Releases: Stable Channel Update for Desktop (googleblog.com)
CVE-2024-4761是V8越界写入漏洞,攻击者可以通过构造恶意代码达成渲染进程RCE(沙箱内)。谷歌在发布的Chrome版本 124.0.6367.207 中修复了该漏洞。
commit:[wasm-gc] Only normalize JSObject targets in SetOrCopyDataProperties
[wasm-gc] Only normalize JSObject targets in SetOrCopyDataProperties (5527397) · Gerrit Code Review (googlesource.com)

根据补丁信息及X上已公开的POC (作者: @buptdsb)可知,该漏洞是由 SetOrCopyDataProperties 函数在转换属性存储模式过程中校验不充分造成的越界写。

关于补丁

[wasm-gc] Only normalize JSObject targets in SetOrCopyDataProperties (5527397) · Gerrit Code Review (googlesource.com)

简单地说就是新引入的WasmObject 对象不该进入JSReceiver::SetOrCopyDataProperties的 Normalize 逻辑。

POC分析

image
会在这里崩溃
image

inobject 个数计算
imageimage
image
image
src/objects/map.h - v8/v8 - Git at Google (googlesource.com)

OOB

inobject被计算为4,前4个32bit被抹零,所以会进入 GetRootForNonJSReceiver
image
image
image

重入JS

在这里切回js
image
image
截图来自:CVE-2024-4761.js (github.com)
很多与对象属性访问相关的历史漏洞(如CVE-2021-30551)都使用过“重入JS用户代码”的模式

利用

@buptsb@mistymntncop 已公开利用方法:
CVE-2024-4947: v8 incorrect AccessInfo for module namespace object causes Maglev type confusion (buptsb.github.io)
CVE-2024-4761: v8 missing check of WasmObject type cast causes type confusion and OOB access (buptsb.github.io)

被清空0~0x10的wasm_array会被识别成字符串
image

gc会把 0xf2000 00000000 当做map
As the instance_type is 0 for now, it’s INTERNALIZED_TWO_BYTE_STRING_TYPE,
so we will call CALL_APPLY(SeqTwoByteString) to gc this object.
image
image

越界写,把o.property's map覆盖为0
image

随后GC,使 o' propertyarr1 重叠,通过访问o的属性更改 arr1length

image
image
image

SeqTwoByteString

双字节字符
 V8 的源代码中,有一个方便查阅的列表,列出了它使用的所有字符串实现:
 从 string.tq 一直往在追,SeqTwoByteString 的内存表示为:
map: Map | raw_hash_field: NameHash | length: int32 | chars[length]: char16
的形式

map为0的对象会被识别成 SeqTwoByteString, 由于instance_type为0,即*(base+8) = 0
image

原因如下:CVE-2024-4947: v8 incorrect AccessInfo for module namespace object causes Maglev type confusion (buptsb.github.io)
image
image

源码参考:string.tq - Chromium Code Search

总结

  1. wasm-gc对象在SetOrCopyDataProperties函数中被normalize时发生oob(被当做JSObject)
  2. 越界写的内容和范围: map_base+5 ~ map_base+4 范围内置零,对于Wasm Array,该对象后紧接着的一个32位会被越界置零。
  3. 利用 property array reallocates 布局内存,使一个fast property(properties[0]=0)紧随 Wasm Array
  4. 触发漏洞,fast property 的 map被置0,利用getter重回JS用户态(避免崩溃)
  5. 触发 GC ,fast property 被混淆为 SeqTwoByteString,可通过访问 fast property 越界写入相邻对象的内部数据。

涉及知识点:

  1. fast property
  2. Object.assign
  3. normalize
  4. map layout
  5. getter / runtime call
  6. GC
  7. SeqTwoByteString

其他:

  1. map layout 查询
  2. 通过 x.tq 查询对象布局
  3. 使用 --soft-abort 关闭 DCHECK

完整利用

需要绕过 heap sandbox
具体方法可参考补丁中的回归测试文件,不赘述

  1. [wasm][sandbox] Fix sandbox escapes via i32 high word (5494364) · Gerrit Code Review (googlesource.com)
  2. [wasm][sandbox] Add WasmTrustedInstanceData::native_module (5529236) · Gerrit Code Review (googlesource.com)