Closed Bug 929539 (slaughterhouse) Opened 6 years ago Closed 5 years ago

[Meta] Secure interaction between platform JS and unprivileged script

Categories

(Core :: DOM: Core & HTML, defect)

x86
macOS
defect
Not set

Tracking

()

RESOLVED FIXED

People

(Reporter: bholley, Assigned: bholley)

References

Details

(Keywords: meta, sec-other)

We run a major security risk every time chrome and content JS interact directly without a layer of protection (either Xrays or bindings) in between. Unfortunately, we're not doing a great job on this front - in our brave new world of hurriedly-built JS-implemented platform features, this is happening a lot. And over the past months, researchers have started to exploit it (bug 856042, bug 924329, bug 928415, etc).

I believe that this is one of the most dire security threats to our platform today. We are currently in a very bad position to respond of this blows up - these exploits are not mitigable with things like ASLR, work reliably across platforms and versions, and each technique can generally be tweaked (with some cleverness) to operate on a number of different exposure points. As such, we cannot afford to handle this in a reactive manner. It's time to launch a coordinated effort to make this stuff secure.

I'm calling this project "slaughterhouse", for two reasons:
(1) It involves killing every COW (Chrome Object Wrapper) in the platform.
(2) It describes the rough situations we'll find ourselves in if this stuff starts getting exploited in the wild. If we chemspill once, people will start digging and we will chemspill many times over.

Here are the major pieces we're going to need, at a high level:
(1) Removal of every single COW (__exposedProps__) from the platform. This generally involves converting APIs to WebIDL.
(2) Improvements to the WebIDL binding machinery to plug any security leaks in JS-implemented WebIDL, and to support any additional features required for the conversions in (1).
(3) Improvements to the wrapper machinery to lock down chrome/content interactions, and allow useful manipulation of non-DOM objects without resorting to .wrappedJSObject.

I will be coordinating this project, but there's too much for me to do alone. Thankfully, a number of other people have volunteered to help:

(1) will be driven by the Security Assurance team, with dchan and dveditz at the helm. They'll prioritize the threats, find owners, and methodically pound away until we have zero non-test uses of __exposedProps__ in our tree.

(2) will be driven by the bindings team. Johnny is in the loop, and Andrew is already working on some of the pieces.

(3) will be driven by me. The two big projects here are (a) flipping the delegation from transparent to opaque when an un-Xrayable unprivileged object is manipulated by chrome without an Xray waiver and (b) implementing useful Xrays to pure ES objects. I won't get too much into the details here.

I'm filing sub-bugs for 1-3. The whole tree will be marked as s-s sec-other, to avoid tipping our hand here.

Let's get moving.
Depends on: SH-APIs
Depends on: SH-bindings
Just one question: strategy for add-ons?
No longer depends on: SH-APIs, SH-bindings
Depends on: SH-wrappers
Depends on: SH-APIs, SH-bindings
Depends on: SH-addons
(In reply to Gabor Krizsanits [:krizsa :gabor] from comment #1)
> Just one question: strategy for add-ons?

Right you are. I just filed bug 929570, which is now officially part (4) of slaughterhouse.
This seems to have the potential to have a significant impact on our test harnesses, some of which may take advantage of security mechanisms you intend to modify.  Many of our harnesses use add-ons, and many of them utilize chrome/content interactions.

Please keep that in mind, and let us know if we can help modify them if/when that turns out to be needed -- preferably with some realistic amount of lead time if those modifications turn out to be non-trivial.
I posted this to security-group on october 22nd, 2014:

Hi All,

One year ago today, I launched Slaughterhouse (original email quoted below). I did so because I was very worried - our rush to implement more things in JS had left us with a wide class of security bugs that researchers were just beginning to uncover.

These bugs were scary because we were ill-prepared to deal with them. they were rooted in JS programming patterns that tended to repeat themselves throughout the ever-growing body of privileged JS running in our products (Firefox Frontend, JS-implemented Web APIs, Addons, etc). We could spot-fix insecure lines as they were reported, but auditing the entire codebase for an insecure _pattern_ is (unfortunately) something that security researchers are much better at doing than we are. That's nothing against our security team - it's just a "many eyes" kind of thing.

Constructing these types of JS privilege escalation exploits requires a lot more Mozilla-specific knowledge than running a fuzzer - so the set of people pursuing them tends to be small, and (I hoped) predisposed to responsible disclosure. But if word got out and the world started watching, I feared that exploits would start pouring in faster than we could respond in any meaningful way. Remember the cascade effect and credibility loss for Java in early 2013? I shudder to imagine the impact that isthereafirefox0day.com would have had on Mozilla.

Software platforms need to be secure by default, and we weren't. So with the help of many brave souls, I spent much of the last year building an ever-stronger security layer between privileged/trusted and unprivileged/untrusted JS.

In total, we landed hundreds of patches and closed more than 100 bugs. For the detail-minded, there's the dependency tree of bug 929539. For everyone else, here's a high-level overview of what we did:
* We greatly expanded the capabilities of XrayWrappers (bug 914970, bug 933681) to provide a safe-by-default interface for a wide variety of non-WebIDL objects that are commonly accessed from privileged JS.
* We flipped the switch to make the long tail of still-non-Xrayable objects opaque from privileged JS (bug 856067).
* We added a security layer that prevents content from passing privileged or cross-origin objects to privileged code (bug 930091, bug 1036214).
* We converted tons and tons of insecure APIs to solid JS-implemented WebIDL machinery (bug 929542, bug 981845, and others).
* We systematically removed capabilities from the previously-ubiquitous __exposedProps__-based COW machinery (bug 1081985 and its dependency tree). A long tail of __exposedProps__ still exists in the tree, but the newly-locked-down machinery makes these cases relatively harmless. The moratorium on them still stands, and they will go away entirely over the next year or two.
* We implemented a lightweight set of tools (Cu.exportFunction, Cu.cloneInto, etc) for exposing simple APIs from privileged JS. This serves the needs of addons and various one-off applications for which WebIDL is overkill.
* We switched Jetpack and GreaseMonkey content scripts to nsExpandedPrincipal, providing them all of the security provisions afforded to chrome code with none of the elevated privileges (bug 821809).
* A long list of smaller improvements, too numerous to list here.

The final pieces landed over the weekend, and I am now comfortable marking Slaughterhouse [DONE]. But as much as I would like to blog about this publicly, I don't think I can, at least for the next year: ESR31 is still largely affected, and fixing it would likely involve backporting more than 100 patches, some of them with significant compat risk. So I ask everyone to keep the lid on this while we put ESR31 out to pasture and let it die a natural death, far from the slaughterhouse.

These changes reached to the very core of the platform, and most of them rattled the foundation enough to break stuff. Our CI was invaluable here, generally uncovering 90% of the breakage and giving me the opportunity to fix up consumers without disruption. For the remaining 10%, I extend my gratitude to the wide set of developers and project managers who put up with regressions and helped get stuff fixed. I gave myself a broad mandate to be aggressive on this project, and I'm honored that I received so little push-back in doing so.

I received a lot of help and support, and kudos are deserved by more people than are practical to list. But I'd like give a special thanks to Gabor and Boris (who probably each reviewed several hundred patches from me this year), as well as Gijs and Ehsan (who ferociously fixed up a dozens of insecure APIs).

With this work (and the compartment-related work that came before it), the rate of new privilege escalation and information leak bugs has dropped to near-zero, and our most notorious security researchers (moz_bug_r_a4, codyc, mariusz, gábor, and others) have been conspicuously silent. I, for one, am happy to start spending my time on other things.

bholley out
Assignee: nobody → bobbyholley
Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Group: core-security → core-security-release
When do we want to open this bug up?
Flags: needinfo?(bobbyholley)
Group: core-security-release
Flags: needinfo?(bobbyholley)
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.