Last Comment Bug 540100 - nsTreeSelection EventListener Use-after-free Remote Code Execution Vulnerability (ZDI-CAN-669)
: nsTreeSelection EventListener Use-after-free Remote Code Execution Vulnerabil...
Status: RESOLVED FIXED
[sg:dupe 375928] fixed by bug 375928
: verified1.9.0.19, verified1.9.1
Product: Core
Classification: Components
Component: XUL (show other bugs)
: 1.9.1 Branch
: All All
: -- normal (vote)
: ---
Assigned To: Olli Pettay [:smaug]
:
Mentors:
Depends on: CVE-2010-0175
Blocks:
  Show dependency treegraph
 
Reported: 2010-01-15 16:38 PST by Brandon Sterne (:bsterne)
Modified: 2010-07-15 19:13 PDT (History)
8 users (show)
dveditz: blocking1.9.0.19+
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---
unaffected
.9+
.9-fixed


Attachments

Description Brandon Sterne (:bsterne) 2010-01-15 16:38:30 PST
Created attachment 421958 [details]
Proof of concept

ZDI-CAN-669: Mozilla Firefox nsTreeSelection EventListener Use-after-free Remote Code Execution Vulnerability

-- ABSTRACT ------------------------------------------------------------

TippingPoint has identified a vulnerability affecting the following  products:

    Mozilla Firefox 3.5.x

-- VULNERABILITY DETAILS -----------------------------------------------

This vulnerability allows remote attackers to execute arbitrary code on software utilizing a vulnerable version of Mozilla's Firefox. User interaction is required in that the victim must visit a malicious website or be coerced into opening a malicious document. 

The specific flaw exists within how the application handles particular events for an nsTreeSelection element. Upon execution of a "select" event the application will access an element without checking to see if it's been previously freed or not. Successful exploitation can lead to code execution under the context of the application.

This vulnerability occurs due to firing an event on an object that has already been freed and can be reproduced with the following code: 
<tree id="tr" flex="1">
    <treechildren>
        <treeitem>
            <treerow>
                <treecell/>
            </treerow>
        </treeitem>
    </treechildren>
</tree>

tree = document.getElementById('tr');
tree.addEventListener("select", function (e) {}, false);
tree.view.selection.timedSelect(0, 5000);    // XXX: fire "select" event
in 5 seconds
tree.view.selection = null;                  // XXX: freed

Upon calling timedSelect on a tree.view.selection object, the application will instantiate a new timer, and call SelectCallback when it fires.

layout/xul/base/src/tree/src/nsTreeSelection.cpp:336

NS_IMETHODIMP nsTreeSelection::TimedSelect(PRInt32 aIndex, PRInt32
aMsec)
{
  PRBool suppressSelect = mSuppressed;

  if (aMsec != -1)
    mSuppressed = PR_TRUE;

  nsresult rv = Select(aIndex);
  if (NS_FAILED(rv))
    return rv;

  if (aMsec != -1) {
    mSuppressed = suppressSelect;
    if (!mSuppressed) {
      if (mSelectTimer)
        mSelectTimer->Cancel();

      mSelectTimer = do_CreateInstance("@mozilla.org/timer;1");
      mSelectTimer->InitWithFuncCallback(SelectCallback, this, aMsec,  
// XXX
                                         nsITimer::TYPE_ONE_SHOT);
    }
  }

  return NS_OK;
}

At this point, a malicious individual will want to free the tree.view.selection the timer has been created for. Once the timer fires, the callback will then be executed. The following code will load the closure representing the callback, and then execute it.

layout/xul/base/src/tree/src/nsTreeSelection.cpp:847
void
nsTreeSelection::SelectCallback(nsITimer *aTimer, void *aClosure)
{
  nsTreeSelection* self = static_cast<nsTreeSelection*>(aClosure);
  if (self) {
    self->FireOnSelectHandler();        // XXX
    aTimer->Cancel();
    self->mSelectTimer = nsnull;
  }
}

The select handler that's been fired, will load the code for the event and then execute it. At this point the tree.view.selection object has been freed.

layout/xul/base/src/tree/src/nsTreeSelection.cpp:827
nsresult
nsTreeSelection::FireOnSelectHandler()
{
  if (mSuppressed || !mTree)
    return NS_OK;

  nsCOMPtr<nsIBoxObject> boxObject = do_QueryInterface(mTree);
  NS_ASSERTION(boxObject, "no box object!");
  if (!boxObject)
     return NS_ERROR_UNEXPECTED;
  nsCOMPtr<nsIDOMElement> elt;
  boxObject->GetElement(getter_AddRefs(elt));
  NS_ENSURE_STATE(elt);

  nsRefPtr<nsPLDOMEvent> event =
    new nsPLDOMEvent(elt, NS_LITERAL_STRING("select"));
  event->RunDOMEventWhenSafe();     // XXX
  return NS_OK;
}

Version(s)  tested: FireFox 3.6.5 
Platform(s) tested: Windows XP SP3

-- CREDIT --------------------------------------------------------------

This vulnerability was discovered by:
    * regenrecht

-- FURTHER DETAILS -----------------------------------------------------

If you have any questions, comments, concerns or require additional details please feel free to contact me via the following:

    Kate Fly
    Security Liaison
    TippingPoint
    kfly@tippingpoint.com
    Office: +1 512.681.8219

We can alternatively be reached via e-mail at:

    zdi-disclosures@tippingpoint.com

Our PGP key is available from:

    http://www.zerodayinitiative.com/documents/disclosures-pgp-key.asc
Comment 1 Olli Pettay [:smaug] 2010-02-08 05:54:27 PST
The PoC explanation isn't quite right.

But anyway, my bad, this is fixed on 1.9.2/trunk, see bug 375928.
Comment 2 Reed Loden [:reed] (use needinfo?) 2010-02-22 15:39:13 PST
Do we have reason to believe that this bug was discovered due to the check-in of the patch in bug 375928?
Comment 3 Olli Pettay [:smaug] 2010-03-04 12:26:19 PST
bug 375928 landed to branches.
Comment 4 Al Billings [:abillings] 2010-03-10 18:01:18 PST
Verified for 1.90 with  Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.19pre) Gecko/2010031005 GranParadiso/3.0.19pre (.NET CLR 3.5.30729) on Windows XP.

Verified for 1.9.1 with  Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.9pre) Gecko/20100310 Shiretoko/3.5.9pre (.NET CLR 3.5.30729).

Interestingly, the PoC will crash the debug builds of each completely but retail works fine.
Comment 5 Olli Pettay [:smaug] 2010-03-11 01:47:38 PST
(In reply to comment #4)
> Interestingly, the PoC will crash the debug builds of each completely but
> retail works fine.
You mean debug builds of 1.9.0.19 and 1.9.1.9 crash?
If so, what does the stack trace look like?
Comment 6 Al Billings [:abillings] 2010-03-11 12:44:04 PST
My debug builds had an issue so I clobbered and rebuilt. I don't see the issue with them now so it is all good.

Note You need to log in before you can comment on or make changes to this bug.