Internet Explorer Script Interjection Code Execution

Derek Soeder
ds.adv....@gmail.com

Reported:       January 26, 2012, to SecuriTeam Secure Disclosure
                http://www.beyondsecurity.com/ssd.html
Published:      August 16, 2012


AFFECTED VENDOR
---------------
Microsoft Corporation


AFFECTED ENVIRONMENTS
---------------------
Internet Explorer 7.0 on Windows XP and Windows Vista
Internet Explorer 8.0 on Windows XP, Windows Vista, and Windows 7
Internet Explorer 9.0.0 through 9.0.8 (MS12-044) on Windows Vista and Windows 7
Other versions of Internet Explorer have not been tested.


UNAFFECTED ENVIRONMENTS
-----------------------
Internet Explorer with MS12-052 hotfix applied


IMPACT
------
The vulnerability described in this document can be exploited by a
malicious Web page to execute arbitrary code with low integrity.
Active scripting must be enabled, and the present exploitation
techniques require that font downloading be set to "Enable" or
"Prompt" and that the "mailto:"; protocol be present.  (These
requirements are satisfied by default on Windows XP, Windows Vista,
and Windows 7.)  The user is presented with a message box which must
be dismissed before code execution can occur.


VULNERABILITY DETAILS
---------------------
Processing of events in Internet Explorer is typically driven by
window messages originating both externally (for instance, due to user
input or paint requests) and internally.  As with all window messages,
these messages are retrieved from the current thread's message queue
by a message loop, which dispatches each message to a window
procedure.  The window procedure, in turn, invokes code to handle the
associated event based on the type of window message.  If the event
handling code can be made to display a message box or dialog, or
otherwise enter a message loop, then another window message relating
to a separate, second event may be dispatched during this "stacked,"
second message loop, meaning the second event will be processed before
the original event has been fully handled.  Processing of the original
event continues only after the second message loop has ended (i.e.,
when the displayed message box or dialog closes).  If the second event
handling code can cause the program's state to become inconsistent
with the first event handling code's expectations--for instance, by
destroying objects referenced in variables local to the first event
handling code--then it should be possible to cause memory corruption
which can be exploited to achieve arbitrary code execution.

A variety of events can result in script running during the event
handler code.  Although it's simple for script to display a message
box or dialog and thereby enter a message loop (e.g., using
window.alert, window.prompt, or window.clipboardData.getData under
default security settings), so far it does not appear that an
interrupting, second event handler can then do anything to disrupt
program state in a way that the first event handler will not
accommodate.  This is understandable, since script must be able to
handle other script running at any time and having arbitrary effects
on program state.  Objects accessible to script should be properly
reference-counted and garbage-collected, and any exception would
constitute a separate vulnerability that could likely be exploited
without use of the flaw described in this document.

In some cases, it's also possible to make MSHTML.DLL enter a message
loop while handling a page rendering event (as opposed to an event
intended to run script).  For one, MSHTML!CMarkup::ProcessURLAction*
is used to check a variety of security settings during page
downloading and rendering; this function calls
URLMON!ProcessUrlAction*, which may display a dialog if the queried
setting's action is set to "Prompt".  Unfortunately, most of the
security settings which default to prompting are now handled through
the yellow security band or notification bar rather than a dialog.

Other avenues for reaching a message loop may be discovered by
backtracking from functions such as DispatchMessageW, MessageBoxW, and
DialogBoxParamW.  One function call of particular interest is a call
to MessageBoxW found in
MSHTML!CMailtoProtocol::DisplayMailClientNotFoundError.  It was
discovered that, if Internet Explorer attempts to download a very long
(approximately 2,030-character) "mailto:"; URL, then
CMailtoProtocol::RunMailClient will fail and call
CMailtoProtocol::DisplayMailClientNotFoundError to display a message
box, thereby entering a message loop.  (The message reads, "Could not
perform this operation because the default mail client is not properly
installed.")  Furthermore, it was found that displaying this message
box while downloading an embedded font (by specifying a long "mailto:";
URL for the font's "src" property) will result in references to
targetable objects remaining on the stack until the message box is
closed.  Thus, a Web page can exploit this vulnerability by declaring
an embedded font with a long "mailto:"; source URL and ensuring that an
event which destroys and replaces targetable objects occurs while the
message box is open.  Although the particulars of the targetable
objects are Internet Explorer version-dependent, exploitation should
generally proceed as typical for an Internet Explorer use-after-free
vulnerability.

Events

The most significant complexity of this vulnerability is understanding
Internet Explorer's event handling.  As mentioned above, event
handling is based on the processing of window messages.  Some window
messages may arise from user input (such as keyboard and mouse
messages), while others may be generated by the operating system (such
as paint and resize messages), but most messages signaling events are
generated interally by Internet Explorer.  These messages use a
message identifier value of 0x8002 and are generated when a "method
call" is added to a queue maintained in Thread Local Storage (TLS), if
the queue is empty.  A method call is simply a function pointer and
associated data representing a callback to be invoked by the event
handling message loop (or any other message loop).  Method calls are
queued using MSHTML!_GWPostMethodCallEx and handled by
MSHTML!GlobalWndOnMethodCall, which the MSHTML!GlobalWndProc window
procedure calls in response to a message 0x8002.

It is important to note that a message 0x8002 will only be posted if
the method call queue is empty and if a message 0x8002 is not
outstanding (being processed or waiting to be processed).  Therefore,
with possibly one minor exception, a second message 0x8002 cannot be
pending while a first message 0x8002 is being processed, meaning a
second method call-based event cannot be handled while a first method
call-based event is being handled, even if the first enters a message
loop.  When exploiting the vulnerability, one event may be based on a
method call, but the other must correspond to user input or some other
type of message.

Although designing a Web page to provoke a user input message without
user interaction is not difficult, Internet Explorer 9 offers another
possibility by introducing asynchronous events.  If a Web page is
viewed in IE9 standards mode, certain events (for example,
body.onfocus) will instead be mediated by messages with an identifier
value of 0x8003, which are generated via
MSHTML!CEventMgr::QueueAsyncEvent ->
MSHTML!CAsyncEventQueue::QueueEvent and processed when GlobalWndProc
calls MSHTML!CAsyncEventQueue::DispatchAllEvents.  If the asynchronous
event handling code enters a message loop, a message 0x8002 could then
be dispatched and cause any queued method calls to be processed.

Example (Internet Explorer 7 and 8)

A simple example of how to reproduce this vulnerability in Internet
Explorer versions 7 and 8 follows.  A Web page contains an empty style
sheet link, a body with an "onmouseover" event handler, and a script
element which creates a new script element and assigns it an
"onreadystatechange" event handler.  The body also has a style which
specifies a large height value, so that the body area will occupy the
full height as well as width of the browser window.  The following
HTML illustrates:

[redacted for now]

When the Web page loads, the presence of the mouse cursor over the
window causes MSHTML!CServer::WndProc to receive a mouse window
message, which it passes to MSHTML!CDoc::OnWindowMessage ->
MSHTML!CDoc::OnMouseMessage.  Further up the call stack, the script of
the body's "onmouseover" event handler runs, setting the empty style
sheet link's "href" attribute to load "MyFont.css".  When the CSS
defining the "MyFont" embedded font is parsed, the long "mailto:"; URL
will ultimately result in
CMailtoProtocol::DisplayMailClientNotFoundError displaying an error
message box, pausing execution of that thread except to process window
messages.  Using the "onmouseover" event handler for this purpose
ensures that the message box will appear during processing of a user
input window message, rather than during processing of a method call
(0x8002) window message, which leaves the method call avenue available
for the second event.

While the message box is showing, our attack server completes its
intentionally delayed response to the request for "slow.js", causing
the client to queue a method call which will run the new script
element's "onreadystatechange" event handler.  Because a method call
(message 0x8002) is not currently being processed--the event being
processed originated instead as a mouse window message--this means the
thread responsible for downloading "slow.js" is free to post a message
0x8002 after it queues the method call.  The window message will then
be dispatched by the message loop that drives the error message box,
causing the "onreadystatechange" event handler to run.  In this
example, the event handler tampers with the object representing the
style sheet, which was still being interpreted at the time the message
box was displayed.  The tampering provokes a crash once the message
box closes and interpretation of the style sheet is allowed to
continue.

Example (Internet Explorer 9)

Now a simple example specific to Internet Explorer 9 is presented.  A
Web page contains a body with an "onfocus" event handler, a style
sheet defining an embedded font and a class which uses it, a "div"
element of the defined class, and a script element which creates a new
script element and assigns it an "onreadystatechange" event handler.
The document begins with a "DOCTYPE" declaration which ensures that
the page will be rendered in IE9 standards mode.  The following HTML
illustrates:

[redacted for now]

In IE9 standards mode, embedded fonts are not downloaded until they're
needed to render the page, meaning that the embedded font's long
"mailto:"; URL is interpreted--and therefore the error message box is
displayed--when the body's "onfocus" event fires.  Because
body.onfocus is handled in IE9 standards mode as an asynchronous event
(message 0x8003), method calls (message 0x8002) remain free to be
dispatched while the message box message loop is on the call stack.
In this example, we expect "slow.js" to finish downloading after
body.onfocus fires and causes the error message box to appear.  The
code in IE that manages the download will queue an
"onreadystatechange" method call for the script, which will be
dispatched by the message box message loop, allowing our Javascript to
execute.  Since IE9 accesses embedded fonts on demand, there will be
references to various object on the stack below the message box
message loop, so if our Javascript tampers with these objects, a crash
will result once the message box is closed.

Walkthrough

To help provide a visual understanding of the vulnerability, a
chronological walkthrough of the Internet Explorer 9 example crash is
presented here.  Following along in the example is recommended.  The
symbols shown correspond to Internet Explorer 9.0.3 on Windows 7 SP1
x86, with MSHTML.DLL version 9.0.8112.16437 loaded at 6D1C0000 and
page heap enabled.

When the example page is loading, a 0x54-byte CTreePos class instance
is allocated on the heap:  (This CTreePos instance will be freed and
its memory reused later.)

  77365ae0 ntdll!RtlAllocateHeap+0x0000023a
  6d423fe1 MSHTML!CHtmRootParseCtx::BeginElement+0x00000035
  6d51b14b MSHTML!CHtmTextParseCtx::BeginElement+0x000000a1
  6d4245a0 MSHTML!CHtmParse::BeginElement+0x00000151
  6d4269aa MSHTML!CHtmParse::ParseBeginTag+0x00000199
  6d422422 MSHTML!CHtmParse::ParseToken+0x00000100
  6d42292a MSHTML!CHtmPost::Exec+0x00000233
  6d427a10 MSHTML!CHtmPost::Run+0x00000041
  6d42793c MSHTML!PostManExecute+0x000001a3
  6d4278a1 MSHTML!PostManResume+0x000000dd
  6d427801 MSHTML!CHtmPost::OnDwnChanCallback+0x00000010
  6d40b4d5 MSHTML!CDwnChan::OnMethodCall+0x0000001f
  6d5a9d09 MSHTML!GlobalWndOnMethodCall+0x00000115
  6d5c9368 MSHTML!GlobalWndProc+0x00000302
  7748c4e7 USER32!InternalCallWinProc+0x00000023
  7748c5e7 USER32!UserCallWinProcCheckWow+0x0000014b
  7748cc19 USER32!DispatchMessageWorker+0x0000035e
  7748cc70 USER32!DispatchMessageW+0x0000000f
  6e8e1b44 IEFRAME!CTabWindow::_TabWindowThreadProc+0x00000722
  6e901a16 IEFRAME!LCIETab_ThreadProc+0x00000317
  759315b0 iertutil!CIsoScope::RegisterThread+0x000000ab
  6e8efd5b IEFRAME!Detour_DefWindowProcA+0x0000006c
  75c4ed6c kernel32!BaseThreadInitThunk+0x0000000e
  773737f5 ntdll!__RtlUserThreadStart+0x00000070
  773737c8 ntdll!_RtlUserThreadStart+0x0000001b

Next, the page's Javascript executes, creating a new script element
with a source of "slow.js".  The idea is that the Web server will
intentionally postpone serving this file for a second or two.  This
arranges for an "onreadystatechange" event to fire after the delay
elapses.

Once the page finishes loading (but before the delay has elapsed), the
"body.onfocus" event fires.  Because the document is in IE9 standards
mode, "body.onfocus" will be queued as an asynchronous event, meaning
it will be mediated by window message 0x8003.  The "body.onfocus"
event handler changes a "div" element's class to a class that uses an
embedded font.  This forces Internet Explorer to attempt to download
the font, which fails due to the long "mailto:"; URL.  Crucially, the
failure triggers a "mailto"-specific message box to be displayed; this
enters a new, top message loop during the original, bottom message
loop's handling of the 0x8003 window message associated with the
"body.onfocus" event.  The call stack, from top to bottom, now looks
like this:

  774a382a USER32!NtUserWaitMessage+0xc
  774a3b27 USER32!DialogBox2+0x207
  774ce0d5 USER32!InternalDialogBox+0xcb
  774ce659 USER32!SoftModalMessageBox+0x68a
  774ce78c USER32!MessageBoxWorker+0x2ca
  774cea08 USER32!MessageBoxTimeoutW+0x7f
  6ea15e86 USER32!MessageBoxExW+0x1b
  774ceaa4 IEFRAME!Detour_MessageBoxExW+0x47
  6db3ac94 USER32!MessageBoxW+0x45
  6db3aaf1 MSHTML!CMailtoProtocol::DisplayMailClientNotFoundError+0x10b
  6db3a2cc MSHTML!CMailtoProtocol::RunMailClient+0x12e
  6db39def MSHTML!CMailtoProtocol::ParseAndBind+0x8b
  76ab1c0b MSHTML!CMailtoProtocol::Start+0xcd
  76a98fb3 URLMON!COInetProt::StartEx+0xf0
  76a9a31f URLMON!CTransaction::StartEx+0x40b
  76a8386c URLMON!CBinding::StartBinding+0x883
  6d438507 URLMON!operator new+0x20
  6d4383ed MSHTML!CTridentFilterHost::BindToMoniker+0xe4
  6d4216f3 MSHTML!CDwnBindData::Bind+0x722
  6d42153b MSHTML!NewDwnBindData+0x189
  6d20c107 MSHTML!CDwnLoad::Init+0x25c
  6d5c1f27 MSHTML!CBitsLoad::Init+0x52
  6d421279 MSHTML!CDwnInfo::SetLoad+0x11e
  6d451257 MSHTML!CDwnInfo::AddDwnCtx+0x67
  6d42c695 MSHTML!CDoc::NewDwnCtx2+0x30a
  6d953c33 MSHTML!CDoc::NewDwnCtx+0x5b
  6d956222 MSHTML!CEmbeddedFontFace::EnsureStartDownload+0x120
  6d955aee MSHTML!CFontFace::CFontFaceSrc::EnsureStartDownload+0x8a
  6d682c20 MSHTML!CFontFace::AddToFamily+0x18c
  6d52ceb2 MSHTML!CStyleSheetArray::BuildFontFaceRuleFamily+0x58
  6d52cd28 MSHTML!ApplyClear+0x113
  6d51bc41 MSHTML!ApplyFontFace+0x1d4
  6d40e103 MSHTML!ApplyFormatInfoProperty+0x33bf
  6d40e424 MSHTML!ApplyAttrArrayValues+0x2bd
  6d5b5344 MSHTML!CStyleSheetArray::Apply+0x34a
  6d47bad8 MSHTML!CMarkup::ApplyStyleSheets+0x6a
  6d47b89e MSHTML!CElement::ApplyStyleSheets+0x4a2
  6d4cddff MSHTML!CElement::ApplyDefaultFormat+0x8b
  6d47b5a0 MSHTML!CBlockElement::ApplyDefaultFormat+0x379
  6d47a5a3 MSHTML!CElement::ComputeFormatsVirtual+0x1a1e
  6d47a4d6 MSHTML!CElement::ComputeFormats+0xe1
  6d47bd39 MSHTML!CTreeNode::ComputeFormats+0xba
  6d482d33 MSHTML!CTreeNode::ComputeFormatsHelper+0x40
  6d360862 MSHTML!CTreeNode::GetFancyFormat+0x32
  6d2d910f MSHTML!CElement::UpdateFormats+0x426
  6d4ce10f MSHTML!CControlledFormatter::Init+0xcc
  6d47fa14 MSHTML!CElement::OnPropertyChangeInternal+0x3fa
  6d49b76b MSHTML!CElement::OnPropertyChange+0x1b
  6d2da8db MSHTML!BASICPROPPARAMS::SetStringProperty+0x36a
  6d0084d6 MSHTML!CFastDOM::CHTMLElement::Trampoline_Set_className+0x61
  6d0cc04d JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  6d0cc968 JSCRIPT9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x117
  6d009a85 JSCRIPT9!Js::JavascriptOperators::SetProperty+0x8c
  6d009a2c JSCRIPT9!Js::JavascriptOperators::OP_SetProperty+0x59
  039507b8 JSCRIPT9!Js::JavascriptOperators::PatchPutValueNoLocalFastPath+0xbc
  6d0084d6 0x39507b8
  6d0083fb JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  6d008332 JSCRIPT9!Js::JavascriptFunction::CallRootFunction+0xb6
  6d0082be JSCRIPT9!ScriptSite::CallRootFunction+0x4f
  6d0cf12c JSCRIPT9!ScriptSite::Execute+0x63
  6d4f24d1 JSCRIPT9!ScriptEngine::Execute+0x11a
  6d4f23fb MSHTML!CListenerDispatch::InvokeVar+0x12a
  6d54ce40 MSHTML!CListenerDispatch::Invoke+0x40
  6d44e624 MSHTML!CEventMgr::_InvokeListeners+0x187
  6d54cf37 MSHTML!CEventMgr::_InvokeListenersOnWindow+0xcc
  6d5db67d MSHTML!CEventMgr::Dispatch+0x3cc
  6d53ba32 MSHTML!CEventMgr::DispatchFocusEvent+0x7d
  6d5e6f74 MSHTML!COmWindowProxy::Fire_onfocus+0x84
  6d5e6ff1 MSHTML!CAsyncEventQueue::DispatchAllEvents+0x7c
  7748c4e7 MSHTML!GlobalWndProc+0x2ed
  7748c5e7 USER32!InternalCallWinProc+0x23
  7748cc19 USER32!UserCallWinProcCheckWow+0x14b
  7748cc70 USER32!DispatchMessageWorker+0x35e
  6e8e1b44 USER32!DispatchMessageW+0xf
  6e901a16 IEFRAME!CTabWindow::_TabWindowThreadProc+0x722
  759315b0 IEFRAME!LCIETab_ThreadProc+0x317
  6e8efd5b IERTUTIL!CIsoScope::RegisterThread+0xab
  75c4ed6c IEFRAME!Detour_DefWindowProcA+0x6c
  773737f5 KERNEL32!BaseThreadInitThunk+0xe
  773737c8 NTDLL!__RtlUserThreadStart+0x70
  00000000 NTDLL!_RtlUserThreadStart+0x1b

As long as the message box remains open, its message loop will
dispatch new window message-mediated events, and control won't return
to Internet Explorer's original message loop.  It doesn't matter which
message loop is dispatching messages, because the same window
procedure is executed in either case.  The only problem is that the
code lower on the call stack was operating on various heap objects
(such as the CTreePos allocated earlier) before control entered the
MessageBox call and became stuck.  Now, if a window message-mediated
event results in the execution of Javascript that modifies or destroys
those heap objects, corruption manifesting as a use-after-free, for
instance, may result.

As belabored in the Vulnerability Details section, not every type of
event can be "stacked" in every situation like this, but certain
different events can.  An 0x8003 window message (for "body.onfocus")
was being processed during the bottom message loop, so if an 0x8002
window message is posted, it will be processed during the top message
loop--and this is exactly what the example has arranged to happen.
Once the delay in serving "slow.js" elapses, an 0x8002 window
message-mediated event (referred to as a "method call") corresponding
to the concluded download will be posted and subsequently processed
during the top message loop.  This method call executes the created
script element's "onreadystatechange" event handler, which destroys
the very "div" element that was in the process of being rendered when
Internet Explorer attempted to download the font and became stuck at
the message box.  The following partial call stack shows "removeChild"
being called from the "onreadystatechange" event handler:

  6d2eb4e3 MSHTML!CElement::ie9_removeChild
  6d0084d6 MSHTML!CFastDOM::CNode::Trampoline_removeChild+0x7b
  6d0cc04d JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  039501af JSCRIPT9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x117
  6d0084d6 0x39501af
  6d0083fb JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  6d008332 JSCRIPT9!Js::JavascriptFunction::CallRootFunction+0xb6
  6d0082be JSCRIPT9!ScriptSite::CallRootFunction+0x4f
  6d0cf12c JSCRIPT9!ScriptSite::Execute+0x63
  6d4f24d1 JSCRIPT9!ScriptEngine::Execute+0x11a
  6d4f23fb MSHTML!CListenerDispatch::InvokeVar+0x12a
  6d35a726 MSHTML!CListenerDispatch::Invoke+0x40
  6d5db834 MSHTML!CEventMgr::Dispatch+0x537
  6d4a5607 MSHTML!CEventMgr::DispatchEvent+0xc9
  6d4a02ff MSHTML!CElement::Fire_onreadystatechange+0x99
  6d5a9d09 MSHTML!CScriptElement::FireOnReadyStateChange+0x3e
  6d5c9368 MSHTML!GlobalWndOnMethodCall+0x115
  7748c4e7 MSHTML!GlobalWndProc+0x302
  7748c5e7 USER32!InternalCallWinProc+0x23
  7748cc19 USER32!UserCallWinProcCheckWow+0x14b
  7748cc70 USER32!DispatchMessageWorker+0x35e
  774a38d7 USER32!DispatchMessageW+0xf
  774a3b27 USER32!DialogBox2+0x15a
  774ce0d5 USER32!InternalDialogBox+0xcb
  774ce659 USER32!SoftModalMessageBox+0x68a
  774ce78c USER32!MessageBoxWorker+0x2ca
  774cea08 USER32!MessageBoxTimeoutW+0x7f
  6ea15e86 USER32!MessageBoxExW+0x1b
  774ceaa4 IEFRAME!Detour_MessageBoxExW+0x47
  6db3ac94 USER32!MessageBoxW+0x45
  6db3aaf1 MSHTML!CMailtoProtocol::DisplayMailClientNotFoundError+0x10b
  6db3a2cc MSHTML!CMailtoProtocol::RunMailClient+0x12e
  6db39def MSHTML!CMailtoProtocol::ParseAndBind+0x8b
  76ab1c0b MSHTML!CMailtoProtocol::Start+0xcd
   ...

The free actually happens in a subsequent method call, which is also
processing during the MessageBox message loop, as shown in the
following partial call stack:

  75c4c3d4 kernel32!HeapFree+0x00000014
  6d5eebed MSHTML!CTreePos::Release+0x00000046
  6d5fdc69 MSHTML!CLayoutBlock::~CLayoutBlock+0x000000ba
  6d5ff5da MSHTML!CFlexBoxBlock::`scalar deleting destructor'+0x00000013
  6d559ee9 
MSHTML!TSmartPointer<CPtsPelParaclient>::~TSmartPointer<CPtsPelParaclient>+0x00000014
  6d5da773 MSHTML!HtmlLayout::SmartDispClient::Release+0x00000023
  6d5da5fb MSHTML!HtmlLayout::FlowBox::ImplicitDestructor+0x0000001d
  6d490144 MSHTML!HtmlLayout::CIE9DocumentLayout::FormatPage+0x00000065
  6d48c517 MSHTML!CCssDocumentLayout::FindOrFormatPage+0x00000272
  6d4872fb MSHTML!CCssDocumentLayout::GetPage+0x00000964
  6d48e06f MSHTML!CMarkupPageLayout::CalcSize+0x0000028c
  6d48de82 MSHTML!CMarkupPageLayout::CalcTopLayoutSize+0x00000101
  6d48fba1 MSHTML!CMarkupPageLayout::DoLayout+0x00000056
  6d47e65a MSHTML!CView::ExecuteLayoutTasks+0x00000034
  6d476a85 MSHTML!CView::EnsureView+0x000003bf
  6d498701 MSHTML!CView::EnsureViewCallback+0x000000b8
  6d5a9d09 MSHTML!GlobalWndOnMethodCall+0x00000115
  6d5c9368 MSHTML!GlobalWndProc+0x00000302
  7748c4e7 USER32!InternalCallWinProc+0x00000023
  7748c5e7 USER32!UserCallWinProcCheckWow+0x0000014b
  7748cc19 USER32!DispatchMessageWorker+0x0000035e
  7748cc70 USER32!DispatchMessageW+0x0000000f
  774a38d7 USER32!DialogBox2+0x0000015a
  774a3b27 USER32!InternalDialogBox+0x000000cb
  774ce0d5 USER32!SoftModalMessageBox+0x0000068a
  774ce659 USER32!MessageBoxWorker+0x000002ca
  774ce78c USER32!MessageBoxTimeoutW+0x0000007f
   ...

At this point, a fully developed exploit might use Javascript to
reallocate and overwrite the memory formerly belonging to the
now-freed CTreePos.  For the sake of this walkthrough, it suffices to
let page heap wipe the freed memory of the CTreePos with 0xF0.

Finally, once the user closes the message box, execution of the
interrupt font downloading and page rendering code continues, but the
code fails to anticipate that the program state has changed during the
MessageBox call.  A pointer on the stack to the destroyed CTreePos is
dereferenced, resulting in an access violation.  The following
register dump, disassembly, and call stack illustrate; notice that EBX
points to stack memory from which a pointer to the destroyed CTreePos
is taken:

  Access violation - code c0000005 (first chance)
  eax=005ba430 ebx=03b5c5c8 ecx=f0f0f0f0 edx=03b5c540 esi=00000000 edi=00557840
  eip=6d47b5d7 esp=03b5c450 ebp=03b5c510 iopl=0 nv up ei pl zr na pe nc
  cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000     efl=00010246
  MSHTML!CElement::ComputeFormatsVirtual+0x1a64:
  6d47b5d7 0fbf4120        movsx   eax,word ptr [ecx+20h]
ds:0023:f0f0f110=????

  6d47b5c5 8b03            mov     eax,dword ptr [ebx]
  6d47b5c7 8b8bd4000000    mov     ecx,dword ptr [ebx+0D4h]
  6d47b5cd 89442420        mov     dword ptr [esp+20h],eax
  6d47b5d1 894c242c        mov     dword ptr [esp+2Ch],ecx
  6d47b5d5 8b08            mov     ecx,dword ptr [eax]
  6d47b5d7 0fbf4120        movsx   eax,word ptr [ecx+20h]

  6d47a5a3 MSHTML!CElement::ComputeFormatsVirtual+0x1a64
  6d47a4d6 MSHTML!CElement::ComputeFormats+0xe1
  6d47bd39 MSHTML!CTreeNode::ComputeFormats+0xba
  6d482d33 MSHTML!CTreeNode::ComputeFormatsHelper+0x40
  6d360862 MSHTML!CTreeNode::GetFancyFormat+0x32
  6d2d910f MSHTML!CElement::UpdateFormats+0x426
  6d4ce10f MSHTML!CControlledFormatter::Init+0xcc
  6d47fa14 MSHTML!CElement::OnPropertyChangeInternal+0x3fa
  6d49b76b MSHTML!CElement::OnPropertyChange+0x1b
  6d2da8db MSHTML!BASICPROPPARAMS::SetStringProperty+0x36a
  6d0084d6 MSHTML!CFastDOM::CHTMLElement::Trampoline_Set_className+0x61
  6d0cc04d JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  6d0cc968 JSCRIPT9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x117
  6d009a85 JSCRIPT9!Js::JavascriptOperators::SetProperty+0x8c
  6d009a2c JSCRIPT9!Js::JavascriptOperators::OP_SetProperty+0x59
  039507b8 JSCRIPT9!Js::JavascriptOperators::PatchPutValueNoLocalFastPath+0xbc
  6d0084d6 0x39507b8
  6d0083fb JSCRIPT9!Js::JavascriptFunction::CallFunction+0xc4
  6d008332 JSCRIPT9!Js::JavascriptFunction::CallRootFunction+0xb6
  6d0082be JSCRIPT9!ScriptSite::CallRootFunction+0x4f
  6d0cf12c JSCRIPT9!ScriptSite::Execute+0x63
  6d4f24d1 JSCRIPT9!ScriptEngine::Execute+0x11a
  6d4f23fb MSHTML!CListenerDispatch::InvokeVar+0x12a
  6d54ce40 MSHTML!CListenerDispatch::Invoke+0x40
  6d44e624 MSHTML!CEventMgr::_InvokeListeners+0x187
  6d54cf37 MSHTML!CEventMgr::_InvokeListenersOnWindow+0xcc
  6d5db67d MSHTML!CEventMgr::Dispatch+0x3cc
  6d53ba32 MSHTML!CEventMgr::DispatchFocusEvent+0x7d
  6d5e6f74 MSHTML!COmWindowProxy::Fire_onfocus+0x84
  6d5e6ff1 MSHTML!CAsyncEventQueue::DispatchAllEvents+0x7c
  7748c4e7 MSHTML!GlobalWndProc+0x2ed
  7748c5e7 USER32!InternalCallWinProc+0x23
  7748cc19 USER32!UserCallWinProcCheckWow+0x14b
  7748cc70 USER32!DispatchMessageWorker+0x35e
  6e8e1b44 USER32!DispatchMessageW+0xf
  6e901a16 IEFRAME!CTabWindow::_TabWindowThreadProc+0x722
  759315b0 IEFRAME!LCIETab_ThreadProc+0x317
  6e8efd5b IERTUTIL!CIsoScope::RegisterThread+0xab
  75c4ed6c IEFRAME!Detour_DefWindowProcA+0x6c
  773737f5 KERNEL32!BaseThreadInitThunk+0xe
  773737c8 NTDLL!__RtlUserThreadStart+0x70
  00000000 NTDLL!_RtlUserThreadStart+0x1b


EXPLOITATION
------------
Exploitation of this vulnerability is typical for a basic
use-after-free condition in Internet Explorer, in that the exploit:
(1) creates an object on the heap, (2) causes the object to be freed
while references to it persist elsewhere, (3) replaces the contents of
the heap memory formerly occupied by the object with arbitrary data,
and (4) causes Internet Explorer to access a stale reference to the
freed object.  In a prepared proof-of-concept EIP control exploit
targeting Internet Explorer 9 (32-bit), these steps were accomplished
by: including two nested, named "div" elements in the HTML; modifying
the outer "div" element to destroy the inner "div" (while the mail
client error message is on the screen); performing a typical heap
spray to store known data at a known address; and creating a large
number of CTreePos-size heap blocks containing specially crafted data
to fill the hole left by the freed inner "div" element.  The specially
crafted data includes a substitute vtable pointer which references
heap-sprayed data at a hard-coded address, another feature typical of
such exploits.  The only step that this exploit cannot accomplish
entirely on its own is triggering Internet Explorer to access the
stale inner "div" element reference--this access occurs only after the
user dismisses the mail client error message.


MITIGATION
----------
Setting the "Downloads" -> "Font download" security setting to
"Disable" ("HKEY_CURRENT_USER\Software\Microsoft\CurrentVersion\Internet
Settings\Zones\<zone-identifier>" -> "1604": REG_DWORD = "3") prevents
exploitation of this vulnerability using the present technique.

Deleting, renaming, or denying read access to the
"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PROTOCOLS\Handler\mailto"
registry key (and
"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\PROTOCOLS\Handler\mailto"
as appropriate) also prevents exploitation using the present
technique; however, after implementing the workaround, confirm that
clicking a "mailto:"; link in any zone does not display a message box.


CONCLUSION
----------
This document presents a long-lived vulnerability in Internet Explorer
which permits arbitrary code execution given default security
settings.  Although current exploitation involves a modest amount of
user interaction and user notification in the form of a mail client
error message, the message is not security-related, and the message
box does not present the user with an option of aborting exploitation.
 Further research into the vulnerability might reveal other means of
exploitation which may change the presented message or reduce or
eliminate the need for user interaction.


GREETINGS
---------
www.thetomatopizza.com
 ^ The best pizza anywhere near DFW; required eating for locals and remotes.

Reply via email to