CVE-2013-3897 – Analysis of Yet Another IE 0-Day

By Gal Badishi | October 8, 2013

While the security community is still discussing the Internet Explorer 0-day (CVE-2013-3893) that was used to perform targeted attacks in the Asia-Pacific region and was public for several weeks without a patch, it appears that another IE 0-day, CVE-2013-3897, is used in attacks on the same region. This time, the targeted version is IE 8 running on Windows XP, and the exploit is triggered only for Korean and Japanese targets. We now provide an analysis of the exploitation techniques used in the in-the-wild attack exploiting CVE-2013-3897, which show great similarity to the exploitation techniques used in CVE-2013-3893.

The exploit abuses a use-after-free vulnerability in Internet Explorer 8, to gain control over EIP. Since IE 8 on Windows XP is DEP-enabled, the attacker uses ROP gadgets found in the Korean/Japanese version to pivot the stack, call VirtualProtect to mark the payload with PAGE_EXECUTE_READWRITE permissions, and jump to the payload. The payload then continues to download executable files masquerading as images, which eventually results in dropping several executable, DLLs and drivers on the machine. The dropped files themselves perform various functions, including disabling AV products, stealing passwords and poisoning DNS lookups. Since Cyvera TRAPS stops the exploitation attempts as they are just starting, no payload is run, and so we will concentrate solely on the exploitation details.

First, let’s look at the ROP gadgets’ addresses:

To see what happens when the browser does not contain the correct MUI pack, consider the first location of a ROP gadget:

1:025> u 0x77BD18D3
77bd18d3 85c0 test eax,eax
77bd18d5 894308 mov dword ptr [ebx+8],eax
77bd18d8 0f84fa000000 je midimap!Unconfigure+0x3c5 (77bd19d8)
77bd18de ff750c push dword ptr [ebp+0Ch]
77bd18e1 50 push eax
77bd18e2 ff153810bd77 call dword ptr [midimap!_imp__lstrcpyW (77bd1038)]
77bd18e8 837de800 cmp dword ptr [ebp-18h],0
77bd18ec 742a je midimap!Unconfigure+0x305 (77bd1918)

Obviously, this can’t be right. And indeed, when we run the exploit, we get an access violation:

(6a8.cb8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=01a4a12c ebx=030416fc ecx=14141414 edx=3050f4a5 esi=01a4a1b0 edi=80004002
eip=7c912e09 esp=01a4a108 ebp=01a4a108 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
7c912e09 668b02 mov ax,word ptr [edx] ds:0023:3050f4a5=????

Other than the value of ecx, the stack trace leaves no room for doubt that indeed we gained control of EIP:

1:025> kv
ChildEBP RetAddr Args to Child
01a4a108 7c80bb20 14141414 3050f4a5 80004002 ntdll!wcscpy+0xb (FPO: [Non-Fpo])
01a4a13c 77bd18e8 14141414 3050f4a5 3cf9da41 kernel32!lstrcpyW+0x1c (FPO: [Non-Fpo])
01a4a180 3d1e5ed9 030416fc 3050f4a5 11cf98b5 midimap!Unconfigure+0x2d5 (FPO: [Non-Fpo])
01a4a1f8 3d1e4e08 001a3ff0 030416fc 00000000 mshtml!CDoc::ScrollPointerIntoView+0xc5
01a4a20c 3d2fcb68 030416e0 02fbd288 00000000 mshtml!CDisplayPointer::ScrollIntoView+0x21
01a4a22c 3d2fcac6 01a4a2bc 01a4a2f8 00000002 mshtml!CHTMLEditor::SelectRangeInternal+0x98
01a4a244 3d302e8e 02fbd288 01a4a2bc 01a4a2f8 mshtml!CHTMLEditor::SelectRange+0x1a
01a4a264 3d1b4d9d 02fbd288 01a4a2bc 01a4a2f8 mshtml!CHTMLEditorProxy::SelectRange+0x25
01a4a284 3d2c1222 001a3ff0 01a4a2bc 01a4a2f8 mshtml!CDoc::Select+0x2f
01a4a32c 3cf01d25 001bfbb0 00989ba0 3cf01cf2 mshtml!CRichtext::select+0xd1
01a4a348 3cf8acf3 02fc3958 00989ba0 02fa3170 mshtml!Method_void_void+0x75
01a4a3bc 3cf96cc1 02fc3958 00001b5d 00000002 mshtml!CBase::ContextInvokeEx+0x5d1
01a4a40c 3cfa29e8 02fc3958 00001b5d 00000002 mshtml!CElement::ContextInvokeEx+0x9d
01a4a438 3cf8a6f9 02fc3958 00001b5d 00000002 mshtml!CInput::VersionedInvokeEx+0x2d
01a4a488 3d7c3a8a 02f92900 00001b5d 00000002 mshtml!PlainInvokeEx+0xea
01a4a4c8 3d7c39d6 00986210 00001b5d 00000409 jscript!IDispatchExInvokeEx2+0xf8
01a4a504 3d7c4f16 00986210 00000409 00000001 jscript!IDispatchExInvokeEx+0x6a
01a4a5c4 3d7c4e70 00001b5d 00000001 00000000 jscript!InvokeDispatchEx+0x98
01a4a5f8 3d7c2d5d 00986210 01a4a62c 00000001 jscript!VAR::InvokeByName+0x135
01a4a644 3d7c4225 00986210 00000001 00000000 jscript!VAR::InvokeDispName+0x7a
01a4a670 3d7c4f83 00986210 00000000 00000001 jscript!VAR::InvokeByDispID+0xce
01a4a80c 3d7c139b 01a4a824 01a4a96c 01a4a96c jscript!CScriptRuntime::Run+0x2abe
01a4a8f4 3d7c12d5 01a4a96c 00000000 02bbca88 jscript!ScrFncObj::CallWithFrameOnStack+0xff
01a4a940 3d7c1103 01a4a96c 00000000 02bbca88 jscript!ScrFncObj::Call+0x8f
01a4a9bc 3d7c384e 00987e00 01a4cdb8 00000000 jscript!CSession::Execute+0x175
01a4aaa4 3d7c36da 00987e00 00000000 00000001 jscript!NameTbl::InvokeDef+0x1b8
01a4ab28 3d7c3a8a 00987e00 00000000 00000002 jscript!NameTbl::InvokeEx+0x129
01a4ab68 3d7c39d6 00986210 00000000 00000002 jscript!IDispatchExInvokeEx2+0xf8
01a4aba4 3d7ab396 00986210 00000002 00000001 jscript!IDispatchExInvokeEx+0x6a
01a4ac34 3cee811f 01a4abf8 00000004 00000002 jscript!NameTbl::InvokeEx+0x372

In order to gain control over EIP and then ESP, the attacker sprays the heap with the value 0×14141414, in a way that remarkably resembles the exact code of the in-the-wild exploit for CVE-2013-3893. The size of the object used to exploit the use-after-free vulnerability is 0×46 bytes. Surprisingly, the attacker left many calls to Math.atan2 with appropriate debug strings. This makes it very easy for us to trace the execution, breaking on jscript!JsAtan2. Here’s what the heap looks like at that range, after the initial heap-spray:

14141404 | 14141414 14141414 14141414 14141414
14141414 | 77bd18d3 77bcef5b 00000000 77bcf519
14141424 | 77bc1118 77bd3e25 77be746a 1414148c
14141434 | 1414148c 00010000 00000040 1414144c
14141444 | 00000000 00000000 00000000 00000000
14141454 | 00000000 00000000 00000000 00000000
14141464 | 00000000 00000000 00000000 00000000
14141474 | 00000000 00000000 00000000 00000000
14141484 | 00000000 00000000 14141414 14141414
14141494 | 14141414 14141414 cccccccc cccccccc

We can see the ROP payload starting at 0×14141414, with the actual payload starting at 0x1414149c (replaced by a bulk of int 3 commands here). The savvy reader will notice a call to VirtualProtect (at address 0x1414142c), changing the protection of 0x1414148c to PAGE_EXECUTE_READWRITE (0×40), and immediately returning to the newly-protected region (see address 0×14141434). To see how we get there, recall that the exploitation stack trace showed that mshtml!CDoc::ScrollPointerIntoView+0xc5 is the return address from the function call that diverted the execution:

1:025> u mshtml!CDoc::ScrollPointerIntoView+0xc0
3d1e5ed4 e8217bdbff call mshtml!QIClassID (3cf9d9fa)
3d1e5ed9 85c0 test eax,eax

Here is a snippet from mshtml!QIClassID:

3cf9da2a 8b03 mov eax,dword ptr [ebx]
3cf9da2c 8365e800 and dword ptr [ebp-18h],0 ss:0023:01a4a168=00000000
3cf9da30 8d4de8 lea ecx,[ebp-18h]
3cf9da33 51 push ecx
3cf9da34 6878daf93c push offset mshtml!IID_IProxyManager (3cf9da78)
3cf9da39 53 push ebx
3cf9da3a bf02400080 mov edi,80004002h
3cf9da3f ff10 call dword ptr [eax]

Meaning that if we can get eax to point to an attacker-controlled field, we have control over EIP. And indeed, after executing the first command in the snippet above, we get:

3cf9da2a 8b03 mov eax,dword ptr [ebx] ds:0023:0304163c=14141414
1:025> p
eax=14141414 ebx=0304163c ecx=000004b0 edx=000000c8 esi=01a4a1b0 edi=01a4a17c
eip=3cf9da2c esp=01a4a15c ebp=01a4a180 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246

This leads us to start executing our ROP chain, which immediately pivots the stack, and continues with the execution of VirtualProtect and the payload itself.


Some More Details

The exploit code explicitly checks that the target uses the Korean or Japanese languages, and also sets a cookie to make sure the exploit won’t run twice on the same target. During exploitation, the code creates 2,000 instances of div elements and sets the title attribute of each instance to the address 0×14141414 (repeated multiple times). It then continues to free 1,000 of the div elements. All of this (including the actual code itself) is all too similar to the in-the-wild CVE-2013-3893 exploit.

The procedure for triggering and exploiting the vulnerability starts with the attacker creating two elements: textarea and address. The textarea handler contains two handlers: one for the onselect() event, and the other one for the onpropertychange() event. The onselect event handler swaps the textarea element in the address element with a newly-created mark element. This step is crucial for the vulnerability to happen.

The onpropertychange handler contains a call to document.execCommand(“Unselect”);, which frees the object. The release is quickly followed by the same heap-spray as before, this time for 1,000 elements, overwriting the freed object.

This whole procedure begins when the javascript code calls the textarea element’s select() method.

This is where the object is freed:

00 016387cc 3cf410bb 026c07f0 3d05fa8b 022222e0 mshtml!CDisplayPointer::Release+0x1f
01 016387d4 3d05fa8b 022222e0 00000000 3d0603f7 mshtml!ClearInterfaceFn+0xf (FPO: [0,0,0])
02 016387e0 3d0603f7 00000000 02226540 00000000 mshtml!CSelectTracker::Destroy+0xe (FPO: [0,0,0])
03 016387f4 3cef008b 00000000 00000001 00000001 mshtml!CSelectTracker::BecomeDormant+0xa5
04 01638808 3cebc32b 00000000 00000001 00000001 mshtml!CSelectionManager::HibernateTracker+0x16
05 01638820 3d338b97 00000000 00000001 00000000 mshtml!CSelectionManager::EnsureDefaultTrackerPassive+0x2d
06 0163883c 3d303dce 00000000 00000000 026ed8b0 mshtml!CSelectTracker::EmptySelection+0x61
07 01638878 3d32e323 00000000 00000000 3d0e0e85 mshtml!CSelectionManager::EmptySelection+0x22c
08 01638884 3d0e0e85 00000002 00000000 00000000 mshtml!CClearSelectionCommand::PrivateExec+0x13 (FPO: [3,0,0])
09 016388a4 3d0e1000 00000002 00000000 00000000 mshtml!CCommand::Exec+0x48
0a 016388c8 3d0e1146 00238430 3cf3b190 000007d7 mshtml!CMshtmlEd::Exec+0x13f
0b 016388f8 3d0ceaed 3cf3b190 000007d7 00000002 mshtml!CEditRouter::ExecEditCommand+0x10a
0c 01638cb8 3d1c74b3 0022fc40 3cf3b190 000007d7 mshtml!CDoc::ExecHelper+0x3cb6
0d 01638cd8 3d2086a9 0022fc40 3cf3b190 000007d7 mshtml!CDocument::Exec+0x24
0e 01638d00 3d1c8e36 02aa8948 000007d7 0163000a mshtml!CBase::execCommand+0x50
0f 01638d38 3d2013e2 00000001 02aa8948 00000000 mshtml!CDocument::execCommand+0x93

And here’s a look at the exact moment of freeing:

CVE-2013-3897 Freeing Object

This is where an allocated object trumps the freed object:

00 01638bc4 3cf4afc2 0222a13c 01638c6c 00000000 mshtml!_HeapAllocString+0x6c
01 01638be8 3cf4715d 01638c6c 00000000 00004000 mshtml!CAttrValue::InitVariant+0x154
02 01638c20 3cf470ab 80010045 3cf83734 01638c6c mshtml!CAttrArray::Set+0x189
03 01638c48 3cf4b15c 026d87ec 80010045 01638c6c mshtml!CAttrArray::Set+0x51
04 01638c7c 3cf4b108 026d87ec 00000000 00004000 mshtml!CAttrArray::SetString+0x44
05 01638c94 3cf11ca9 026d87ec 0222a13c 00000000 mshtml!BASICPROPPARAMS::SetString+0x69
06 01638cd4 3cf21b2e 3cf83734 001f0422 0222a13c mshtml!PROPERTYDESC::HandleStringProperty+0x142
07 01638cf0 3d00ce3f 001f0422 0222a13c 01638dc0 mshtml!PROPERTYDESC::CallHandler+0x1e
08 01638d9c 3d00ccbe 026d87e0 00000002 02aa46e0 mshtml!CBase::VersionedSetAttribute+0x161
09 01638dd0 3d00cd70 026d87e0 02aa46e0 00000008 mshtml!CElement::ie8_setAttribute+0x24

And here it is visually:

CVE-2013-3897 Overwriting Freed Object

Finally, the select() method of the textarea element triggers the vulnerability:

0163a180 3d1e4699 026C6924 3050f4a5 11cf98b5 mshtml!QIClassID+0x45
0163a1f8 3d1e35d3 0020a1b0 026C6924 00000000 mshtml!CDoc::ScrollPointerIntoView+0xc5
0163a20c 3d2fab70 025b7208 00208ac8 00000000 mshtml!CDisplayPointer::ScrollIntoView+0x21
0163a22c 3d2faace 0163a2bc 0163a2f8 00000002 mshtml!CHTMLEditor::SelectRangeInternal+0x98
0163a244 3d300e96 00208ac8 0163a2bc 0163a2f8 mshtml!CHTMLEditor::SelectRange+0x1a
0163a264 3d1b38fd 00208ac8 0163a2bc 0163a2f8 mshtml!CHTMLEditorProxy::SelectRange+0x25
0163a284 3d2bf256 0020a1b0 0163a2bc 0163a2f8 mshtml!CDoc::Select+0x2f
0163a32c 3cf01e05 00212d10 029c2db8 3cf01dd2 mshtml!CRichtext::select+0xd1

And EIP is ours:

CVE-2013-3897 Controlling EIP

An old version of Cyvera TRAPS has been tested against the zero-day exploit variant found in-the-wild, and was able to stop it in multiple different places. Cyvera TRAPS does not depend on signatures, and thus does not need to get updated in order to stop zero-day attacks. Additionally, the attacks are prevented at the early exploitation stage, meaning that no payload is run, no files are dropped, and no modification is made to the computer.

I would like to thank Shahar S., a senior researcher of Cyvera, for his contribution to this post.


For more information, please contact us!