wrong compartment while structured cloning a cross-compartment ArrayBuffer

RESOLVED FIXED in Firefox 49

Status

()

defect
RESOLVED FIXED
3 years ago
2 years ago

People

(Reporter: sfink, Assigned: sfink)

Tracking

({csectype-other, sec-high})

unspecified
mozilla51
Points:
---
Dependency tree / graph
Bug Flags:
qe-verify -

Firefox Tracking Flags

(firefox47 wontfix, firefox48 wontfix, firefox49+ fixed, firefox-esr4549+ fixed, firefox50+ fixed, firefox51 fixed)

Details

(Whiteboard: [post-critsmash-triage][adv-main49+][adv-esr45.4+])

Attachments

(2 attachments, 2 obsolete attachments)

(Assignee)

Description

3 years ago
testcase
When transferring the contents of an ArrayBuffer during a structured clone, a cross-compartment ArrayBuffer is unwrapped, but then the detach call happens in the original compartment. If there is more than one view on that ArrayBuffer, all views after the second will then fail to be detached (because we have an InnerViewsTable *on the compartment* that holds all views but the first.)

As a result, these views (eg typed arrays) will still have pointers into the ArrayBuffer's data, which is a huge correctness violation as well as a set up for lots of race conditions if the data has been transferred between threads. Furthermore, if the buffer gets GC'd, it's a very controllable UAF.

JS shell example:

b = new ArrayBuffer(100);
ta = new Int32Array(b);
ta[0] = 17;

g = newGlobal();
g.b = b;
ta2 = g.eval("new Int32Array(b)");

g.serialize(b, [b]);
// gc();

print(ta[0]);
print(ta2[0]); // This is 17, should be undefined. With the gc(), it is a UAF and will probably crash.

In the browser, you'd use postMessage to detach the buffer.
(Assignee)

Comment 1

3 years ago
[Tracking Requested - why for this release]: This bug goes back to at least Fx45, and is trivially exploitable.
(Assignee)

Comment 2

3 years ago
Asking for review on this patch, but I'm not sure in what form we'd want to land this to be discreet. We can discuss that during the approval process. (Same thing for tests. I have a test, but it makes things horribly obvious.)
Attachment #8773527 - Flags: review?(jwalden+bmo)
(Assignee)

Updated

3 years ago
Assignee: nobody → sphink
Status: NEW → ASSIGNED
Comment on attachment 8773527 [details] [diff] [review]
Enter the transferred ArrayBuffer's compartment before stealing its data

Review of attachment 8773527 [details] [diff] [review]:
-----------------------------------------------------------------

*gulp*  I keep missing when our tracking of buffer views changes.  First it was a linked list, then it was something, then something else, now this.  CAN'T WE JUST GET IT RIGHT THE FIRST TIME.  :-)

::: js/src/vm/ArrayBufferObject.cpp
@@ +1062,1 @@
>                  MOZ_ASSERT_IF(buf.dataPointer() == nullptr, offset == 0);

The more these build up, the more I prefer #ifdef DEBUG around an if with MOZ_ASSERTs, but this is fine.
Attachment #8773527 - Flags: review?(jwalden+bmo) → review+
Group: core-security → javascript-core-security
(Assignee)

Comment 4

3 years ago
MozReview-Commit-ID: 90tALXT2BVr
Attachment #8775698 - Flags: review?(jwalden+bmo)
(Assignee)

Updated

3 years ago
Attachment #8773527 - Attachment is obsolete: true
(Assignee)

Comment 5

3 years ago
MozReview-Commit-ID: 90tALXT2BVr
Attachment #8775701 - Flags: review?(jwalden+bmo)
(Assignee)

Updated

3 years ago
Attachment #8775698 - Attachment is obsolete: true
Attachment #8775698 - Flags: review?(jwalden+bmo)
Attachment #8775701 - Flags: review?(jwalden+bmo) → review+
(Assignee)

Comment 6

3 years ago
My original comment was a little too revealing.
Attachment #8775728 - Flags: review?(jwalden+bmo)
(Assignee)

Comment 7

3 years ago
Comment on attachment 8775728 [details] [diff] [review]
Version of the patch with a more mundane description

[Security approval request comment]
How easily could an exploit be constructed based on the patch?

If someone is familiar with the security properties of compartments, it's pretty easy. This gives you a read/write UAF with a completely controllable offset.

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?

No, I changed to a less revealing comment.

Which older supported branches are affected by this flaw?

all of them

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?

Easy to create. They should be nearly identical, though I suspect enough of the structured clone code will have changed slightly that they might not apply cleanly. I looked back to esr45 and the code is functionally identical.

How likely is this patch to cause regressions; how much testing does it need?

Unlikely. Without this fix, some things would have worked that should not. (Specifically, if you transferred a buffer via postMessage, its views would continue to "work" when they shouldn't.)

[Approval Request Comment]
Fix Landed on Version: not yet landed at this time
Risk to taking this patch (and alternatives if risky): low risk
String or UUID changes made by this patch: none

Approval Request Comment
[Feature/regressing bug #]: 1061404
[User impact if declined]: exploitable UAF
[Describe test coverage new/current, TreeHerder]: it fixes my test case, but I'm afraid to push it to a publicly visible place
[Risks and why]: theoretically somebody could be depending on views of detached buffers working, but if so we need to break them ASAP
[String/UUID change made/needed]: none
Attachment #8775728 - Flags: sec-approval?
Attachment #8775728 - Flags: approval-mozilla-release?
Attachment #8775728 - Flags: approval-mozilla-esr45?
Attachment #8775728 - Flags: approval-mozilla-beta?
Attachment #8775728 - Flags: approval-mozilla-aurora?
Attachment #8775728 - Flags: review?(jwalden+bmo) → review+
This is pretty bad and revealing from your comments. I'm going to sec-approve for trunk checkin but it needs to wait until August 16 so we're two weeks into the cycle so we don't overly expose this to anyone watching checkins.
Attachment #8775728 - Flags: sec-approval?
Attachment #8775728 - Flags: sec-approval+
Attachment #8775728 - Flags: approval-mozilla-release?
Comment on attachment 8775728 [details] [diff] [review]
Version of the patch with a more mundane description

Sec-high, approving for all affected branches. Based on Al's last comment this ought to be committed on Aug 16th and not before that. Aurora50+, Beta49+, ESR45+
Attachment #8775728 - Flags: approval-mozilla-esr45?
Attachment #8775728 - Flags: approval-mozilla-esr45+
Attachment #8775728 - Flags: approval-mozilla-beta?
Attachment #8775728 - Flags: approval-mozilla-beta+
Attachment #8775728 - Flags: approval-mozilla-aurora?
Attachment #8775728 - Flags: approval-mozilla-aurora+
(Assignee)

Updated

3 years ago
Blocks: 1287298, 1240984
https://hg.mozilla.org/mozilla-central/rev/a9213b054219
Status: ASSIGNED → RESOLVED
Last Resolved: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla51
Group: javascript-core-security → core-security-release
Flags: qe-verify-
Whiteboard: [post-critsmash-triage]
Whiteboard: [post-critsmash-triage] → [post-critsmash-triage][adv-main49+][adv-esr45.4+]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.