Closed
Bug 571106
(CVE-2010-2753)
Opened 15 years ago
Closed 15 years ago
nsTreeSelection Dangling Pointer Remote Code Execution Vulnerability (ZDI-CAN-755)
Categories
(Core :: XUL, defect)
Core
XUL
Tracking
()
People
(Reporter: reed, Assigned: smaug)
References
Details
(Keywords: fixed1.9.0.20, verified1.9.1, verified1.9.2, Whiteboard: [sg:critical?][critsmash:patch])
Attachments
(1 file, 1 obsolete file)
982 bytes,
patch
|
neil
:
review+
dveditz
:
approval1.9.2.7+
dveditz
:
approval1.9.1.11+
dveditz
:
approval1.9.0.next+
|
Details | Diff | Splinter Review |
ZDI-CAN-755: Mozilla Firefox nsTreeSelection Dangling Pointer Remote Code Execution Vulnerability
-- ABSTRACT ------------------------------------------------------------
TippingPoint has identified a vulnerability affecting the following
products:
Mozilla Firefox 3.6.x
-- VULNERABILITY DETAILS -----------------------------------------------
This vulnerability allows remote attackers to execute arbitrary code on
vulnerable installations of Mozilla Firefox. User interaction is
required to exploit this vulnerability in that the target must visit a
malicious page or open a malicious file.
The specific flaw exists within the implementation of XUL <tree>
element's "selection" attribute. There is an integer overflow when
calculating the bounds of a new selection range. When calling
adjustSelection on this manged range both ranges are deleted leaving a
dangling reference. A remote attacker can exploit this vulnerability to
execute arbitrary code under the context of the browser.
View of XUL <tree> element exposes "selection" attribute. This in turn
allows user to precisely choose set of tree's rows to be shown as
selected. The way class nsTreeSelection
(layout/xul/base/src/tree/src/nsTreeSelection.cpp) is implemented is
quite interesting: with a linked list of nsTreeRange instances where
nsTreeRange represents single continuous range of selected rows (and
possibly a pointer to the next range). nsTreeSelection holds directly
only one pointer, to the first range, mFirstRange.
What is also important to note: whenever any nsTreeRange instance is
deleted, delete (inside destructor) is called recursively on the next
linked instances as well.
Imagine we have the following piece of Javascript code:
[1] sel = tree.treeBoxObject.view.selection;
[2] sel.rangedSelect(0, 0x7fffffff, true);
[3] sel.adjustSelection(1, 1);
At [1] we grab the reference to selection object. At this moment
mFirstRange is null, no row is selected, so there is no need for any
range to keep track of.
Then [2] we call method rangedSelect(). From
nsTreeSelection::RangedSelect():
...
PRInt32 start = aStartIndex < aEndIndex ? aStartIndex : aEndIndex;
PRInt32 end = aStartIndex < aEndIndex ? aEndIndex : aStartIndex;
...
nsTreeRange* range = new nsTreeRange(this, start, end);
if (!range)
return NS_ERROR_OUT_OF_MEMORY;
range->Invalidate();
if (aAugment && mFirstRange)
mFirstRange->Insert(range);
else
mFirstRange = range;
...
That makes mFirstRange being set to range <0, 2G>, or more precisely
(yet in ad hoc pseudo code):
mFirstRange = {
min: 0,
max: 2G,
prev: null,
next: null
}
And at [3] we hit integer overflow that causes a lot of trouble. From
nsTreeSelection::AdjustSelection(PRInt32 aIndex, PRInt32 aCount):
...
nsTreeRange* newRange = nsnull;
PRBool selChanged = PR_FALSE;
nsTreeRange* curr = mFirstRange;
while (curr) {
if (aCount > 0) {
// inserting
if (aIndex > curr->mMax) {
...
}
else if (aIndex <= curr->mMin) {
...
}
else {
// adjustment happen inside the range.
// break apart the range and create two ranges
ADD_NEW_RANGE(newRange, this, curr->mMin, aIndex - 1);
ADD_NEW_RANGE(newRange, this, aIndex + aCount, curr->mMax +
aCount);
selChanged = PR_TRUE;
}
}
else {
...
}
curr = curr->mNext;
}
delete mFirstRange;
mFirstRange = newRange;
...
As we are calling AdjustSelection(1, 1), two ADD_NEW_RANGE() are
executed.
This means that something like <0, 0>.Insert(<2, -2G>) will be called.
Notice that because of integer overflow lower bound (2) is above higher
bound (-2G).
void Insert(nsTreeRange* aRange) {
if (mMin >= aRange->mMax)
aRange->Connect(mPrev, this);
else if (mNext)
mNext->Insert(aRange);
else
aRange->Connect(this, nsnull);
}
So, now <2, -2G>.Connect(mPrev = null, <0, 0>):
void Connect(nsTreeRange* aPrev = nsnull, nsTreeRange* aNext = nsnull)
{
if (aPrev)
aPrev->mNext = this;
else
mSelection->mFirstRange = this;
if (aNext)
aNext->mPrev = this;
mPrev = aPrev;
mNext = aNext;
}
Which results in:
mFirstRange = {
min: 2,
max: -2G,
prev: null,
next: {
min: 0,
max: 0,
prev: mFirstRange,
next: null
}
}
But we can not forget about the epilogue of AdjustSelection():
delete mFirstRange;
mFirstRange = newRange;
Final result: both ranges (<2, -2G>, <0, 0>) are deleted and mFirstRange
points at deleted range <0, 0>.
-- CREDIT --------------------------------------------------------------
This vulnerability was discovered by:
* regenrecht
Reporter | ||
Comment 1•15 years ago
|
||
![]() |
||
Updated•15 years ago
|
blocking2.0: --- → ?
Comment 2•15 years ago
|
||
On Mac 3.5.11pre and 3.6.6pre it looks like a null-deref DoS
3.5: bp-2d7a4637-6ce5-47b0-867c-a41ca2100609
3.6: bp-c584be08-5186-402e-bee2-f6af42100609
I get a similar Mac trunk crash to Reed's Linux one above.
bp-e901aaaf-6b71-4603-8d96-64f722100609
The code looks the same though, so I'd expect all versions to have the same issues as described in comment 0.
Assignee | ||
Updated•15 years ago
|
Assignee: nobody → Olli.Pettay
Assignee | ||
Comment 3•15 years ago
|
||
Make sure nsTreeRange is created in a proper way.
Other cases when nsTreeRange is created manually without the macro are safe.
Attachment #450359 -
Flags: review?(neil)
Comment 4•15 years ago
|
||
Comment on attachment 450359 [details] [diff] [review]
simple version
>+ PRInt32 start = macro_start; \
Not sure why you created a temporary for macro_start but still double-evaluated macro_end?
>+ PRInt32 end = start < macro_end ? macro_end : start; \
Nit: start > macro_end is the (hopefully unlikely) bug case; start = macro_end and start < macro_end are equally likely, so this hurts branch prediction.
Assignee | ||
Comment 5•15 years ago
|
||
ok, I'll tweak the patch a bit.
Whiteboard: [sg:critical?] → [sg:critical?][needs review]
Updated•15 years ago
|
Whiteboard: [sg:critical?][needs review] → [sg:critical?][needs review][critsmash:patch]
Assignee | ||
Comment 6•15 years ago
|
||
I'll update the patch tomorrow.
Assignee | ||
Comment 7•15 years ago
|
||
Attachment #450359 -
Attachment is obsolete: true
Attachment #451552 -
Flags: review?(neil)
Attachment #450359 -
Flags: review?(neil)
Updated•15 years ago
|
Attachment #451552 -
Flags: review?(neil) → review+
Assignee | ||
Comment 8•15 years ago
|
||
Status: NEW → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
Assignee | ||
Updated•15 years ago
|
Whiteboard: [sg:critical?][needs review][critsmash:patch] → [sg:critical?][critsmash:patch]
Assignee | ||
Updated•15 years ago
|
Attachment #451552 -
Flags: approval1.9.2.6?
Attachment #451552 -
Flags: approval1.9.1.11?
Comment 9•15 years ago
|
||
Comment on attachment 451552 [details] [diff] [review]
patch
Approved for 1.9.2.6 and 1.9.1.11, a=dveditz for release-drivers
Attachment #451552 -
Flags: approval1.9.2.6?
Attachment #451552 -
Flags: approval1.9.2.6+
Attachment #451552 -
Flags: approval1.9.1.11?
Attachment #451552 -
Flags: approval1.9.1.11+
Assignee | ||
Comment 10•15 years ago
|
||
Comment 11•15 years ago
|
||
Verified for 1.9.1.11 using attached testcase and build 1 (Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.11) Gecko/20100701 Firefox/3.5.11 (.NET CLR 3.5.30729)).
Verified for 1.9.2.7 with its build 1 (Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.7) Gecko/20100701 Firefox/3.6.7 (.NET CLR 3.5.30729)).
Verified that 1.9.1.10 and 1.9.2.6 both crash with the testcase.
Keywords: verified1.9.1,
verified1.9.2
blocking2.0: ? → beta2+
Updated•15 years ago
|
Alias: CVE-2010-2753
Comment on attachment 451552 [details] [diff] [review]
patch
Requesting approval1.9.0.next on this patch so that we can take it in upcoming Camino 2.0.x security and stability updates. If approved, I'll handle the checkins, unless the patch author requests otherwise.
Attachment #451552 -
Flags: approval1.9.0.next?
Comment 13•15 years ago
|
||
Comment on attachment 451552 [details] [diff] [review]
patch
Approved for 1.9.0.20, a=dveditz
Attachment #451552 -
Flags: approval1.9.0.next? → approval1.9.0.next+
Checking in layout/xul/base/src/tree/src/nsTreeSelection.cpp;
/cvsroot/mozilla/layout/xul/base/src/tree/src/nsTreeSelection.cpp,v <-- nsTreeSelection.cpp
new revision: 1.63; previous revision: 1.62
done
Keywords: fixed1.9.0.20
Comment 15•15 years ago
|
||
We need an in-tree regression test for this.
Group: core-security
Flags: in-testsuite?
Reporter | ||
Updated•15 years ago
|
Depends on: CVE-2010-2760
Updated•14 years ago
|
Group: core-security
You need to log in
before you can comment on or make changes to this bug.
Description
•