在本文中,我将利用CVE-2024-5830,这是 Chrome 的 JavaScript 引擎 v8 中的一个类型混淆错误,我于 2024 年 5 月将其报告为错误 342456991。该错误已在版本126.0.6478.56/57中修复。此错误允许通过一次访问恶意网站在 Chrome 的渲染器沙箱中执行远程代码执行 (RCE)。
V8 中的对象映射和映射转换
本节包含理解该漏洞所需的对象图和转换中的一些背景材料。熟悉这些内容的读者可以跳至下一节。
映射(或隐藏类)的概念对于 JavaScript 解释器来说相当基础。它表示对象的内存布局,对于优化属性访问至关重要。已经有很多好文章对这个主题进行了更详细的介绍。我特别推荐 Mathias Bynens 的“ JavaScript 引擎基础:形状和内联缓存”。
映射包含属性描述符数组 ( DescriptorArrays
),其中包含有关每个属性的信息。它还包含有关对象元素及其类型的详细信息。
具有相同属性布局的对象之间可以共享映射。例如,以下对象都具有一个a
类型为 (31 位整数) 的属性SMI
,因此它们可以共享同一个映射。
o1 = {a : 1};
o2 = {a : 10000}; //<------ same map as o1, MapA
映射还会记录对象中的属性类型。例如,以下对象具有与和o3
不同的映射,因为其属性的类型为( ),而不是:o1
o2
a
double
HeapNumber
SMI
o3 = {a : 1.1};
当向对象添加新属性时,如果新对象布局的地图尚不存在,则会创建新的地图。
o1.b = 1; //<------ new map with SMI properties a and b
当发生这种情况时,新旧地图通过转换关联起来:
%DebugPrint(o2);
DebugPrint: 0x3a5d00049001: [JS_OBJECT_TYPE]
- map: 0x3a5d00298911 [FastProperties]
...
- All own properties (excluding elements): {
0x3a5d00002b19: [String] in ReadOnlySpace: #a: 10000 (const data field 0), location: in-object
}
0x3a5d00298911: [Map] in OldSpace
- map: 0x3a5d002816d9 <MetaMap (0x3a5d00281729 )>
...
- instance descriptors #1: 0x3a5d00049011
- transitions #1: 0x3a5d00298999
0x3a5d00002b29: [String] in ReadOnlySpace: #b: (transition to (const data field, attrs: [WEC]) @ Any) -> 0x3a5d00298999
...
请注意,的映射o2
包含到另一个映射的转换(0x3a5d00298999
),这是为的新创建的映射o3
:
%DebugPrint(o3);
DebugPrint: 0x3a5d00048fd5: [JS_OBJECT_TYPE]
- map: 0x3a5d00298999 [FastProperties]
...
- All own properties (excluding elements): {
0x3a5d00002b19: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object
0x3a5d00002b29: [String] in ReadOnlySpace: #b: 1 (const data field 1), location: properties[0]
}
0x3a5d00298999: [Map] in OldSpace
- map: 0x3a5d002816d9 <MetaMap (0x3a5d00281729 )>
...
- back pointer: 0x3a5d00298911
...
o2
相反, ( )的映射0x3a5d00298911
作为后向指针存储在这个新映射中。一个映射可以在 中存储多个转换TransitionArray
。例如,如果将另一个属性c
添加到o2
,则TransitionArray
将包含两个转换,一个到属性b
,另一个到属性c
:
o4 = {a : 1};
o2.c = 1;
%DebugPrint(o4);
DebugPrint: 0x2dd400049055: [JS_OBJECT_TYPE]
- map: 0x2dd400298941 [FastProperties]
- All own properties (excluding elements): {
0x2dd400002b19: [String] in ReadOnlySpace: #a: 1 (const data field 0), location: in-object
}
0x2dd400298941: [Map] in OldSpace
- map: 0x2dd4002816d9 <MetaMap (0x2dd400281729 )>
...
- transitions #2: 0x2dd400298a35 Transition array #2:
0x2dd400002b39: [String] in ReadOnlySpace: #c: (transition to (const data field, attrs: [WEC]) @ Any) -> 0x2dd400298a0d
0x2dd400002b29: [String] in ReadOnlySpace: #b: (transition to (const data field, attrs: [WEC]) @ Any) -> 0x2dd4002989c9
...
SMI
当对象中的类型字段被分配一个double
(<