Hi everyone
Last week, Microsoft released MS13-038 as part of the updates for May 2013. This specifically patches CVE-2013-1347, which is used in the compromise of U.S. Department of Labor website recently (well, I’m sure this is not the only website). For those who still does not know, this is a use-after-free vulnerability affecting only IE8. In the rest of the post, I will give a quick walk-though of how the use-after-free is determined.
Walk-Through
Let’s look at the POC from metasploit:
This POC results in the following access violation:
(670.70c): Access violation – code c0000005 (!!! second chance !!!)
eax=6374672c ebx=02db4708 ecx=02dce188edx=00002895 esi=020bf0b8 edi=00000000
eip=00002895 esp=020bf088 ebp=020bf0a4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
00002895 ?? ???
With the following stacktrace:
01 020bf088 63602718 mshtml!CElement::Doc+0x7
02 020bf0a4 636026a3 mshtml!CTreeNode::ComputeFormats+0xb9
03 020bf350 63612a85 mshtml!CTreeNode::ComputeFormatsHelper+0x44
04 020bf360 63612a45 mshtml!CTreeNode::GetFancyFormatIndexHelper+0x11
05 020bf370 63612a2c mshtml!CTreeNode::GetFancyFormatHelper+0xf
06 020bf380 63717f30 mshtml!CTreeNode::GetFancyFormat+0x35
07 020bf38c 63717f4e mshtml!ISpanQualifier::GetFancyFormat+0x5a
08 020bf39c 63717afe mshtml!SLayoutRun::HasInlineMbp+0x10
09 020bf3ac 63724f88 mshtml!SRunPointer::HasInlineMbp+0x53
0a 020bf3e4 6373a5a1 mshtml!CLayoutBlock::GetIsEmptyContent+0xf1
0b 020bf41c 6382ed01 mshtml!CLayoutBlock::GetIsEmptyContent+0x3f
0c 020bf468 63702e23 mshtml!CBlockContainerBlock::BuildBlockContainer+0x250
…..
With these information and simple back-tracing, we can see that the CTreeNode class object is crucial in leading to the crash.
……
In a nutshell, this sequence of execution eventually tries to call the 0x1C-th virtual function of CTreeNode->pAnotherClassObject.
To be sure of what’s going on, we now turn on page heap and run the POC again.
(638.10c): Access violation – code c0000005 (!!! second chance !!!)
eax=f0f0f0f0 ebx=137d63e0 ecx=137d60f8 edx=00000000 esi=037cf0b8 edi=00000000
eip=6363fcc6 esp=037cf08c ebp=037cf0a4 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!CElement::Doc+0x2:
6363fcc6 8b5070 mov edx,dword ptr [eax+70h] ds:0023:f0f0f160=????????
0:008> !heap -p -a ebx
address 137d63e0 found in
_HEAP @ 240000
HEAP_ENTRY Size Prev Flags UserPtr UserSize – state
137d63b8 0011 0000 [03] 137d63e0 0004c – (busy)
7c949564 ntdll!RtlAllocateHeapSlowly+0x00000044
7c918f01 ntdll!RtlAllocateHeap+0x00000e64
637724f2 mshtml!CMarkup::InsertElementInternal+0x0000022a
6377234c mshtml!CDoc::InsertElement+0x0000008a
637727f5 mshtml!CCommentElement::`scalar deleting destructor’+0x0000023d
63772991 mshtml!CElement::InsertBeforeHelper+0x000000d1
637728b7 mshtml!CElement::insertBefore+0x0000003c
63772a38 mshtml!CElement::appendChild+0x00000039
63791a83 mshtml!Method_IDispatchpp_IDispatchp+0x000000ca
636430c9 mshtml!CBase::ContextInvokeEx+0x000005d1
6366418a mshtml!CElement::ContextInvokeEx+0x0000009d
6362b6ce mshtml!CInput::VersionedInvokeEx+0x0000002d
63642eec mshtml!PlainInvokeEx+0x000000ea
633a6d37 jscript!IDispatchExInvokeEx2+0x000000f8
633a6c75 jscript!IDispatchExInvokeEx+0x0000006a
633a9cfe jscript!InvokeDispatchEx+0x00000098
0:008> !heap -p -a poi(ebx)
address 137d60f8 found in
_HEAP @ 240000
HEAP_ENTRY Size Prev Flags UserPtr UserSize – state
137d60d0 000e 0000 [03] 137d60f8 00038 – (free DelayedFree)
7c949e1c ntdll!RtlFreeHeapSlowly+0x00000037
7c927553 ntdll!RtlFreeHeap+0x000000f9
636b52c6 mshtml!CGenericElement::`vector deleting destructor’+0x0000003d
63628a50 mshtml!CBase::SubRelease+0x00000022
63640d1b mshtml!CElement::PrivateRelease+0x00000029
6363d0ae mshtml!PlainRelease+0x00000025
63663c03 mshtml!PlainTrackerRelease+0x00000014
633a10b4 jscript!VAR::Clear+0x0000005c
6339fb4a jscript!GcContext::Reclaim+0x000000ab
6339fd33 jscript!GcContext::CollectCore+0x00000113
63405594 jscript!JsCollectGarbage+0x0000001d
633a92f7 jscript!NameTbl::InvokeInternal+0x00000137
633a6650 jscript!VAR::InvokeByDispID+0x0000017c
633a9c0b jscript!CScriptRuntime::Run+0x00002989
633a5ab0 jscript!ScrFncObj::CallWithFrameOnStack+0x000000ff
633a59f7 jscript!ScrFncObj::Call+0x0000008f
This shows that while the CTreeNode object is still valid and has a reference to CTreeNode->pAnotherObject, it has actually been freed. So this verifies that this is a use-after-free vulnerability.
Alternatively, we could also set breakpoints and observe on CTreeNode::CTreeNode and CTreeNode::Release (and also CGenericElement::CGenericElement and CGenericElement::’deleting destructor’, if you like), which produces the following sequence of events.
—————————
…
—————————
[Constructor CGenericElement]
CGenericElement::CGenericElement : 137D60F8
address 137d60f8 found in
_HEAP @ 240000
HEAP_ENTRY Size Prev Flags UserPtr UserSize – state
137d60d0 000e 0000 [03] 137d60f8 00038 – (busy)
mshtml!CGenericElement::`vftable’
7c949564 ntdll!RtlAllocateHeapSlowly+0x00000044
7c918f01 ntdll!RtlAllocateHeap+0x00000e64
635db42e mshtml!CGenericElement::CreateElement+0x00000018
635a67f5 mshtml!CreateElement+0x00000043
637917c0 mshtml!CMarkup::CreateElement+0x000002de
63791929 mshtml!CDocument::CreateElementHelper+0x00000052
637918a2 mshtml!CDocument::createElement+0x00000021
635d3820 mshtml!Method_IDispatchpp_BSTR+0x000000d1
636430c9 mshtml!CBase::ContextInvokeEx+0x000005d1
63643595 mshtml!CBase::InvokeEx+0x00000025
63643832 mshtml!DispatchInvokeCollection+0x0000014b
635e1cdc mshtml!CDocument::InvokeEx+0x000000f1
63642f30 mshtml!CBase::VersionedInvokeEx+0x00000020
63642eec mshtml!PlainInvokeEx+0x000000ea
633a6d37 jscript!IDispatchExInvokeEx2+0x000000f8
633a6c75 jscript!IDispatchExInvokeEx+0x0000006a
—————————
[Constructor CTreeNode]
CTreeNode::CTreeNode : 137D63E0
pAnotherObject : 137D60F8
pAnotherObject_VFT : 635DB4C8
pAnotherObject_Type :
(635db4c8) mshtml!CGenericElement::`vftable’ | (63777ff8) mshtml!CHeaderElement::`vftable’
Exact matches:
mshtml!CGenericElement::`vftable’ = <no type information>
—————————
…
—————————
[Release CTreeNode]
CTreeNode::Release : 137D63E0
pAnotherObject : 137D60F8
pAnotherObject_VFT : 635DB4C8
—————————
…
—————————
[Destructor CGenericElement]
CGenericElement::’deleting destructor’ : 137D60F8
VFT : F0F0F0F0
address 137d60f8 found in
_HEAP @ 240000
HEAP_ENTRY Size Prev Flags UserPtr UserSize – state
137d60d0 000e 0000 [03] 137d60f8 00038 – (free DelayedFree)
7c949e1c ntdll!RtlFreeHeapSlowly+0x00000037
7c927553 ntdll!RtlFreeHeap+0x000000f9
636b52c6 mshtml!CGenericElement::`vector deleting destructor’+0x0000003d
63628a50 mshtml!CBase::SubRelease+0x00000022
63640d1b mshtml!CElement::PrivateRelease+0x00000029
6363d0ae mshtml!PlainRelease+0x00000025
63663c03 mshtml!PlainTrackerRelease+0x00000014
633a10b4 jscript!VAR::Clear+0x0000005c
6339fb4a jscript!GcContext::Reclaim+0x000000ab
6339fd33 jscript!GcContext::CollectCore+0x00000113
63405594 jscript!JsCollectGarbage+0x0000001d
633a92f7 jscript!NameTbl::InvokeInternal+0x00000137
633a6650 jscript!VAR::InvokeByDispID+0x0000017c
633a9c0b jscript!CScriptRuntime::Run+0x00002989
633a5ab0 jscript!ScrFncObj::CallWithFrameOnStack+0x000000ff
633a59f7 jscript!ScrFncObj::Call+0x0000008f
—————————
…
The crash occurs after CGenericElement::’deleting destructor’. We gather a few other points from the print-out:
- The CGenericElement class object is allocated (CGenericElement::CGenericElement)
- In CTreeNode::CTreeNode, the CGenericElement object is inserted into CTreeNode object (as a CElement object)
- In CTreeNode::Release, the CGenericElement object is still valid. In fact, CTreeNode::Release only changes a DWORD at [CTreeNodeObject+0x40], presumably to mark that this CGenericElement object would be destroyed on GarbageCollect().
- The CElement::Doc() function had originally intended to call CGenericElement->VFT[0x1C] == CElement::SecurityContext(void):
As a side note, the size of CGenericElement object is 0x38 bytes. So the attacker would have to create multiple fake objects of this size for exploitation, of which we would not cover here.
Final Remarks
The analysis here is based purely on the POC, thus arriving at the conclusion that CGenericElement is the object involved in the use-after-free. exp-sky claims to have produce a POC which uses the CAnchorElement object instead.
Because the attacker could execute code remotely upon successful exploitation of this bug, affected organizations (well, in fact everyone) should not take this lightly. Our customers can rest easy to know that they are protected from this vulnerability. Other counter-measures were also mentioned by my colleague in an earlier blog post.
I’m sure we’re not seeing the last of such vulnerabilities. Until then, goodbye!