Blog

Technical Analysis of CVE-2013-3147

In July, Microsoft released a patch for a memory-corruption vulnerability in the Internet Explorer (IE) Web browser. The vulnerability enabled remote attackers to execute arbitrary code or cause a denial of service through a crafted or compromised website — also known as a drive-by download.

This vulnerability is particularly interesting because it is so simple that even some tutorials on the web can trigger it, and it is unique to IE. The vulnerability exists in onbeforeeditfocus event. Only Internet Explorer supports this event (detailed information can be found at http://help.dottoro.com/ljclqecn.php).

Vulnerability
The vulnerability triggers when the document markup is manipulated inside the handler of onbeforeeditfocus event. It leads to a crash in mshtml!CElement::BubbleBecomeCurrent when the instruction tries to access the freed pointer.

Following is the state of registers at the time of crash.

0:008> r
 eax=00000004 ebx=00000000 ecx=06034f88 edx=80000035 esi=06082fb0
 edi=048466a8 eip=636b31fe esp=037cf9b8 ebp=037cf9d4 iopl=0 nv up ei pl zr na pe nc
 cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
 mshtml!CElement::BubbleBecomeCurrent+0xa7:
 636b31fe 8b7604 mov esi,dword ptr [esi+4] ds:0023:06082fb4=????????

At this stage ESI holds the freed pointer.

0:008> !heap -p -a esi
 address 06082fb0 found in
 _DPH_HEAP_ROOT @ 141000
 in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
 5802a58: 6082000 2000
 7c927553 ntdll!RtlFreeHeap+0x000000f9
 63625834 mshtml!CTreeNode::Release+0x0000002d
 63640cea mshtml!PlainRelease+0x00000033
 63662fec mshtml!CTreeNode::NodeRelease+0x0000002a
 635bd2d4 mshtml!CElement::BecomeCurrent+0x00000145
 636b31eb mshtml!CElement::BubbleBecomeCurrent+0x00000094
 637eeb74 mshtml!CElement::BubbleBecomeCurrent+0x0000004c
 636b5dd5 mshtml!CDoc::PumpMessage+0x0000096a
 635f1fea mshtml!CDoc::OnMouseMessage+0x0000055d
 635ef664 mshtml!CDoc::OnWindowMessage+0x000007af
 6364207a mshtml!CServer::WndProc+0x00000078
 7e418734 USER32!InternalCallWinProc+0x00000028
 7e418816 USER32!UserCallWinProcCheckWow+0x00000150
 7e4189cd USER32!DispatchMessageWorker+0x00000306
 7e418a10 USER32!DispatchMessageW+0x0000000f
 02562ec9 IEFRAME!CTabWindow::_TabWindowThreadProc+0x00000461

Following was the size of allocation where ESI is pointing:

ESI: 6082fb0
 address 06082fb0 found in
 _DPH_HEAP_ROOT @ 141000
 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
 5802a58: 6082fb0 4c - 6082000 2000
 7c918f01 ntdll!RtlAllocateHeap+0x00000e64
 635a8225 mshtml!CHtmRootParseCtx::BeginElement+0x00000030
 635bc1e9 mshtml!CHtmTextParseCtx::BeginElement+0x0000006c
 635a8420 mshtml!CHtmParse::BeginElement+0x000000b7
 635a93b4 mshtml!CHtmParse::ParseBeginTag+0x000000fe
 635a6bb6 mshtml!CHtmParse::ParseToken+0x00000082
 635a7ff4 mshtml!CHtmPost::ProcessTokens+0x00000237
 635a734c mshtml!CHtmPost::Exec+0x00000221
 635ac2b8 mshtml!CHtmPost::Run+0x00000015
 635ac21b mshtml!PostManExecute+0x000001fd
 635cece9 mshtml!CPostManager::PostManOnTimer+0x00000134
 6364de62 mshtml!GlobalWndOnMethodCall+0x000000fb
 6363c3c5 mshtml!GlobalWndProc+0x00000183
 7e418734 USER32!InternalCallWinProc+0x00000028
 7e418816 USER32!UserCallWinProcCheckWow+0x00000150
 7e4189cd USER32!DispatchMessageWorker+0x00000306

But the story doesn’t end here. The instruction on which we are getting an exception is moving the pointer at [ESI+4] to ESI. So looking to the pointer, which is at [ESI+4], is important. If we monitor the ESI, then we will see the following sequence (note: the value of ESI is changed from the previous one because I collected this information at the second run):

ESI: 48bafb0 [ESI+4]: 6050fb0 [[ESI+4]]: 5ff0fd0 [[[ESI+4]]]: 635ba8c0
ESI: 48bafb0 [ESI+4]: 0 <---------------------- Exception

The exception instruction is expecting 6050fb0 at [ESI+4]. But because the pointer is freed, we hit an exception. The address 6050fb0 is the pointer to object 5ff0fd0 of type 635ba8c0 as we can see in the above lines and can also verify with the below windbg command.

0:008> ln 635ba8c0
 (635ba8c0) mshtml!CBodyElement::`vftable' | (637812c0) mshtml!CStackDataAry
<unsigned short,128>::`vftable'
 Exact matches:
 mshtml!CBodyElement::`vftable' = <no type information>

Possible Code Execution Path:

This situation can lead to code execution because the value at [ESI+4] propagates to  the CElement::BecomeCurrent method which again calls the CElement::Doc method to access the vftable and call a function.

Following is the disassembly of the faulty function:

Our program crashes here:

1st

 

loc_636b31BF:

2nd

 

Here, a few checks are getting the value of EBX. But EBX is also in control, and the value of EBX remains the same as it was in the beginning of the function call.

CElement::BecomeCurrent:

3rd

 

CElement::Doc:

4th

This isn’t the first IE vulnerability in which the CElement::Doc function played a role — in at least one other past vulnerabilityCElement::Doc function played a key role in the code execution.

(Thanks to my colleagues Abhishek Singh and Yichong Lin for their suggestions.)