Sunday, November 10, 2013

The Technical Aspects of Exploiting IE Zero-Day CVE-2013-3897

Just last month, during our work at spiderlabs research, the team and myself had the chance to analyze CVE-2013-3897 Use-after-free vulnerability.
This vulnerability was basically a result of an object type CDisplayPointer being freed and used again when a richtext tries to scroll the pointer into the current view.
A flow that includes a selection, that occurs under "onpropertychange" event, and a DOM that contains a textarea structure (detailed below) results a possible remote code execution.

Breaking it to down
1. Create a TEXTAREA and apply a different element as a child using applyElement. This will place theaddress element as the child of the textarea element.
2. Trigger a select event on the TEXTAREA element to create an instance of DisplayPointer.
3. Inside onselect event change the value property of the TEXTAREA element, which in turn will fire the eventonpropertychange. For example, usage of appendChild or swapNode will cause this behavior. 
Notice that id_2 (“address” element) is a child of the TEXTAREA element. By swapping that element we remove it from layout of “textarea” and insert a different element, therefore the value property changes.
4. The event onpropertychange is triggered
5. In the next stage we basically need to change the position of the display pointer within the TEXTAREA layout. In the original exploit document.execCommand(“UnSelect”) was used. However, selecting a different element, executing the SelectAll command or any operation that causes a DisplayPointer position change will also work. 
The attacker used "UnSelect" command
6.  The JavaScript selection causes a call to CDisplayPointer::ScrollIntoView, which tries to set a new position for the DisplayPointer. At this stage, the reference to CMarkupPointer is already released by the CDisplayPointer::Release function (as a result of the “UnSelect” command) and therefore points to an attacker-controlled heap area.
The flow eventually gets into QIClassID, which tries to execute “CMarkupPointer::QueryInterface” (located at offset 0x0 in CMarkupPointer’s virtual table).
QIClassID (use): 
Blog 2
QIClassID disassemble crash point

At the crash we end up with the following stack trace:

CMarkupPointer freed and then used by QIClassID:
Most of this post was originally generated here: