Closed Bug 1144991 (CVE-2015-0816) Opened 9 years ago Closed 9 years ago

Privilege escalation from resource:// document (e.g. pdf viewer) (ZDI-CAN-2826)

Categories

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

x86
All
defect
Not set
critical

Tracking

()

VERIFIED FIXED
mozilla39
Tracking Status
firefox36 - wontfix
firefox37 + verified
firefox38 + verified
firefox39 + verified
firefox-esr31 37+ verified
firefox-esr38 --- verified
b2g-v1.4 --- fixed
b2g-v2.0 --- fixed
b2g-v2.0M --- fixed
b2g-v2.1 --- fixed
b2g-v2.1S --- fixed
b2g-v2.2 --- fixed
b2g-master --- fixed

People

(Reporter: dveditz, Assigned: bzbarsky)

References

Details

(Keywords: csectype-priv-escalation, sec-moderate, Whiteboard: [adv-main37+][adv-esr31.6+])

Attachments

(3 files, 1 obsolete file)

Attached file zip file of part 2 —
From winning Pwn2Own entry by Mariusz Mlynski [2/2]:

-----------------------
2. PRIVILEGE ESCALATION
-----------------------

This is an extension of the cross-origin bypass vulnerability. The internal pdf viewer in Firefox executes with the "resource://pdf.js/web/viewer.html" security principal. It's unprivileged, but the handling of "resource:" principals with respect to loading permissions is incorrect, as documented in the source code:


>>>>>>>>>>>>>>>>>>>>>> /caps/nsScriptSecurityManager.cpp >>>>>>>>>>>>>>>>>>>>>>>
NS_IMETHODIMP
nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
                                                   nsIURI *aTargetURI,
                                                   uint32_t aFlags)
{
(...)

    // Check for chrome target URI
    rv = NS_URIChainHasFlags(targetBaseURI,
                             nsIProtocolHandler::URI_IS_UI_RESOURCE,
                             &hasFlags);
    NS_ENSURE_SUCCESS(rv, rv);
    if (hasFlags) {
        (...)

        // resource: and chrome: are equivalent, securitywise
        // That's bogus!!  Fix this.  But watch out for
        // the view-source stylesheet?
        bool sourceIsChrome;
        rv = NS_URIChainHasFlags(sourceBaseURI,
                                 nsIProtocolHandler::URI_IS_UI_RESOURCE,
                                 &sourceIsChrome);
        NS_ENSURE_SUCCESS(rv, rv);
        if (sourceIsChrome) {
            return NS_OK;
        }
        if (reportErrors) {
            ReportError(nullptr, errorTag, sourceURI, aTargetURI);
        }
        return NS_ERROR_DOM_BAD_URI;
    }

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


The nsIProtocolHandler::URI_IS_UI_RESOURCE flag is set for chrome:, resource:, and moz-icon: URIs. They're all free to load other URIs with this flag, including chrome-privileged pages under "chrome:". This bogus treatment of resource: principals paves the way for a privilege escalation in the event of a cross-origin bypass, such as the one described above. The attacker can use the session history confusion to execute code in the context of the pdf viewer and then re-use the said attack to compromise a privileged page, allowing for javascript code execution with the system principal.
Attached file demo.html —
This one might be a little more complete (req's common.js from the .zip file).
bz is the expert on loading permissions. Boris, let me know if you have the cycles to take this, or whether you want me to go take a crack at it. I can do so tomorrow morning, if needed.
Flags: needinfo?(bzbarsky)
See Also: → CVE-2015-0818
So just to be clear, this bug on its own is not exploitable without having some way to violate same-origin policy (in this case, bug 1144988 was used).

Also to be clear, there are various cases where we simply allow chrome:// bits through CheckLoadURI; for example any case that uses ALLOW_CHROME plus has the URI whitelisted in the chrome registry.

The important thing for the exploit, in addition to bug 1144988, was that we allowed loading the chrome:// URI in an iframe.

So I think the simplest/safest fix here is to change the "allow loading chrome:// from resource://" bit to only happen when ALLOW_CHROME is set.  That is, ALLOW_CHROME would allow loading any chrome:// URI from a resource:// URI, not just whitelisted ones.

A more daring fix, with more potential addon fallout, would be to simply drop the "resource:// is allowed to load chrome://" bit entirely.  I'm fairly certain that nothing in Firefox depends on it.  We _may_ have dependencies on chrome:// loading resource:// (e.g. the XML prettyprint stylesheet and maybe the viewsource stylesheet).  Would be worth checking.

The "more daring" option might be able to prevent some sort of addon fingerprinting things, maybe, but is really not needed to prevent the whole "script execution with system principal" thing.
Flags: needinfo?(bzbarsky)
This is the m-c patch, but also applies to aurora and beta
Attachment #8580220 - Flags: review?(bobbyholley)
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
I filed bug 1145314 on the "more daring fix" bit.
Blocks: 1145314
Comment on attachment 8580220 [details] [diff] [review]
Be a bit more restrictive about when a URI_IS_UI_RESOURCE source is allowed to link to a URI_IS_UI_RESOURCE URI that doesn't have the same scheme

Approval Request Comment
[Feature/regressing bug #]: None; this has been around for a while.
[User impact if declined]: Some possibly-fishy loads can be performed, but on its
   own nothing fatal.
[Describe test coverage new/current, TreeHerder]: Test coverage is probably
   somewhat lacking....
[Risks and why]: The main risk is breaking parts of the Firefox UI or addons. 
   Specifically, the most likely breakage is resource:// URLs loading subframes
   that contain chrome:// URLs.  I expect this risk to be fairly low, which is
   the only reason I'm asking for approvals at all.
[String/UUID change made/needed]: None
Attachment #8580220 - Flags: approval-mozilla-release?
Attachment #8580220 - Flags: approval-mozilla-beta?
Attachment #8580220 - Flags: approval-mozilla-aurora?
Comment on attachment 8580223 [details] [diff] [review]
Patch for esr31; identical except for the filename

[Approval Request Comment]
If this is not a sec:{high,crit} bug, please state case for ESR consideration:
   Unrated so far, so requesting just in case.
User impact if declined: See comment 7
Fix Landed on Version: 39
Risk to taking this patch (and alternatives if risky): See comment 7
String or UUID changes made by this patch: None

See https://wiki.mozilla.org/Release_Management/ESR_Landing_Process for more info.
Attachment #8580223 - Flags: approval-mozilla-esr31?
Keywords: sec-critical
Comment on attachment 8580220 [details] [diff] [review]
Be a bit more restrictive about when a URI_IS_UI_RESOURCE source is allowed to link to a URI_IS_UI_RESOURCE URI that doesn't have the same scheme

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

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?  I think the actual code change pretty much paints as much of a bulls-eye as the comments do, though the comments do point out that document loading is really the relevant thing here.

Which older supported branches are affected by this flaw?  All of them.  Here's the same code in a slightly old branch: http://mxr.mozilla.org/aviarybranch/source/caps/src/nsScriptSecurityManager.cpp#1290

If not all supported branches, which bug introduced the flaw?

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?  This should be pretty easy to backport, even to aviarybranch.  ;)

How likely is this patch to cause regressions; how much testing does it need?  This is the fun bit.  The regression risk is definitely nonzero, especially for addons....  The more testing we can get, the better.
Attachment #8580220 - Flags: sec-approval?
Comment on attachment 8580220 [details] [diff] [review]
Be a bit more restrictive about when a URI_IS_UI_RESOURCE source is allowed to link to a URI_IS_UI_RESOURCE URI that doesn't have the same scheme

sec-approval+ and approval for aurora and beta. I'll leave release approval for the release management team.
Attachment #8580220 - Flags: sec-approval?
Attachment #8580220 - Flags: sec-approval+
Attachment #8580220 - Flags: approval-mozilla-beta?
Attachment #8580220 - Flags: approval-mozilla-beta+
Attachment #8580220 - Flags: approval-mozilla-aurora?
Attachment #8580220 - Flags: approval-mozilla-aurora+
Attachment #8580223 - Flags: approval-mozilla-esr31? → approval-mozilla-esr31+
[Tracking Requested - why for this release]:
Comment on attachment 8580220 [details] [diff] [review]
Be a bit more restrictive about when a URI_IS_UI_RESOURCE source is allowed to link to a URI_IS_UI_RESOURCE URI that doesn't have the same scheme

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

Thanks for writing this up! r=bholley with comments addressed.

::: caps/nsScriptSecurityManager.cpp
@@ +750,5 @@
>      if (hasFlags) {
>          if (aFlags & nsIScriptSecurityManager::ALLOW_CHROME) {
> +            // Allow a URI_IS_UI_RESOURCE source to link to a URI_IS_UI_RESOURCE
> +            // target if ALLOW_CHROME is set (i.e. we're not loading a
> +            // document).

Please explain this in a bit more detail, as you did over IRC - ALLOW_CHROME is a flag that we pass on all loads _except_ docshell loads (since docshell loads run the loaded content with its origin principal). So we're effectively allowing resource://, chrome://, and moz-icon:// source URIs to load resource://, chrome://, and moz-icon:// files, so long as they're not loading it as a document.

@@ +764,3 @@
>              if (!targetScheme.EqualsLiteral("chrome")) {
> +                // for now don't change behavior for resource: or moz-icon: and
> +                // just allow them.

Nit - I think this should go at the top of the block, then the sourceIsUIResource stuff, then the whitelist stuff.

@@ +784,5 @@
>          }
>          return NS_ERROR_DOM_BAD_URI;
>      }
>  
>      // Check for target URI pointing to a file

There's a similar "that's bogus" comment below here. Is there anything we could do for file:// loads? I suspect not really, since file:// URIs don't have privileged principals, and the dangers of loading them are basically equivalent whether or not they're loaded as a document.
Attachment #8580220 - Flags: review?(bobbyholley) → review+
I wont' be able to land this until 4-5 hours from now.
(In reply to Not doing reviews right now from comment #13)
> I wont' be able to land this until 4-5 hours from now.

I take it that the patch is ready but you're just unavailable to land. (We can find someone else to land so that we can gtb.) Can you please confirm?
Flags: needinfo?(bzbarsky)
Flags: needinfo?(bzbarsky)
Oh, sorry.  Patch needs the review comments applied too.
bholley - Can you take care of applying your review comments and attaching a new patch while bz is out?
Flags: needinfo?(bobbyholley)
bholley and bz's comments have convinced me that this is not exploitable _by_itself_ without a SOP violation so I'm lowering the severity, but that doesn't really lower its _importance_ since it's part of a privilege escalation chain.

Add-ons do so many crazy things I can't say none of them use the functionality this blocks. Yeah, maybe Firefox 38 is safer to get feedback and give add-ons time to re-write around it.
(In reply to Daniel Veditz [:dveditz] from comment #17)
> bholley and bz's comments have convinced me that this is not exploitable
> _by_itself_ without a SOP violation so I'm lowering the severity, but that
> doesn't really lower its _importance_ since it's part of a privilege
> escalation chain.
> 
> Add-ons do so many crazy things I can't say none of them use the
> functionality this blocks. Yeah, maybe Firefox 38 is safer to get feedback
> and give add-ons time to re-write around it.

This patch is relatively "safe", at least compared to the other alternatives. Putting it in 37 seems like a good compromise to me IMO - it's probably fine, but we want at least the chance to respin before shipping it to our entire user base.
Flags: needinfo?(bobbyholley)
I'm happier trying for 37 than waiting 8 weeks for 38
Keywords: sec-highsec-moderate
Comment on attachment 8580297 [details] [diff] [review]
Be a bit more restrictive about when a URI_IS_UI_RESOURCE source is allowed to link to a URI_IS_UI_RESOURCE URI that doesn't have the same scheme.  r=bholley

Carrying forward Aurora and Beta approval. We're not going to take this fix on release.
Attachment #8580297 - Flags: approval-mozilla-release-
Attachment #8580297 - Flags: approval-mozilla-beta+
Attachment #8580297 - Flags: approval-mozilla-aurora+
checkin-needed as bz can't land now and I don't see bholley on irc.
Keywords: checkin-needed
This seems to have broken a test in browser-chrome-2: 

https://treeherder.mozilla.org/logviewer.html#?job_id=7816411&repo=mozilla-inbound

I'm not seeing either bz or bholley on irc, so I'm not sure where that leaves us.
(In reply to Wes Kocher (:KWierso) from comment #24)
> This seems to have broken a test in browser-chrome-2:
Flags: needinfo?(bobbyholley)
INFO TEST-START | browser/components/uitour/test/browser_no_tabs.js
INFO checking window state
Entering test test_windowless_UITour
Adding UITour permission to the test page.
Console message: Security Error: Content at resource://gre-resources/hiddenWindow.html may not load or link to chrome://global/content/mozilla.xhtml.
Console message: 1426808735046	Toolkit.GMP	WARN	GMPInstallManager.parseResponseXML got node name: html, expected: updates
Console message: [JavaScript Error: "1426808735047	Toolkit.GMP	ERROR	GMPInstallManager.simpleCheckAndInstall Could not check for addons: {"target":{},"message":"got node name: html, expected: updates"}" {file: "resource://gre/modules/Log.jsm" line: 749}]
Console message: 1426808735134	Services.HealthReport.HealthReporter	WARN	Saved state file does not exist.
Looking at this with MattN now.
Flags: needinfo?(bobbyholley)
There's also a buffer overflow in that log, which is alarming, but it is pre-existing. I'll try to figure out something about that...
(In reply to Wes Kocher (:KWierso) from comment #29)
> bc3 also seems to have gone orange with this patch:
> https://treeherder.mozilla.org/logviewer.html#?job_id=7815533&repo=mozilla-
> inbound

The relevant error there is:
  Security Error: Content at resource://gre-resources/hiddenWindow.html may not load or link to chrome://global/content/mozilla.xhtml.

(I filed bug 1145443 for the buffer overflow.)
>  Security Error: Content at resource://gre-resources/hiddenWindow.html may not load or
> link to chrome://global/content/mozilla.xhtml.

Oh.  This is the "people like sticking random iframes in the hidden window" business.  :(

And of course it's a non-Mac-only problem because on Mac hiddenwindow is a chrome:// URI.

One option is to just specifically whitelist hiddenwindow.  Another is to change it to loading from a chrome:// (but not system principal) URI on non-Mac.  A third is to give it the system principal... I thought we were avoiding that on purpose.
Talked to Boris. We're just going to special-case the hiddenDOMWindow for now.
Comment on attachment 8580416 [details] [diff] [review]
followup.  Allow the hidden window to link to chrome things even though most resource:// URIs can't

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

::: caps/nsScriptSecurityManager.cpp
@@ +785,5 @@
>              }
>          }
>  
> +        // Special-case the hidden window: it's allowed to load
> +        // URI_IS_UI_RESOURCE no matter what.

Please add a bug reference to the followup to fix this terrible business.
Attachment #8580416 - Flags: review?(bobbyholley) → review+
And https://hg.mozilla.org/integration/mozilla-inbound/rev/ae2217c25cee because muscle memory and I had it as nsCString when I test-compiled, apparently....
Per IRC discussion, backed out from the GECKO3150esr_2015021713_RELBRANCH so we can spin a 31.5.2 build in case we don't want to ship this in ESR 31.5.1. It's still on default for ESR 31.6.

https://hg.mozilla.org/releases/mozilla-esr31/rev/e647fda03631
On mobile - we get the same results, displays before and after the fix. I am not sure if there is something physical to observe. we did copy the files unziped and the demo on the SD card.
Is there a way to verify it for mobile?
Flags: needinfo?(dveditz)
ni bz and bholley to help Ioanna understand the test case for mobile.
Flags: needinfo?(bzbarsky)
Flags: needinfo?(bobbyholley)
Alias: CVE-2015-0816
Does mobile ship pdf.js?
Flags: needinfo?(bzbarsky)
Just confirmed with nalexander that we only ship pdf.js in Fennec Nightly.
Does this bug only reproduce with pdf.js? Are there other scenarios that we need to test?
pdfjs was just used here as a steppingstone to chrome access.

The steppingstone part is hard to reproduce with something else.  The cross site scripting (which is covered by bug 1144988) should be possible to reproduce this with an arbitrary cross-site url, I'd think.
Flags: needinfo?(bobbyholley)
Given that this was verified on desktop, is a platform fix, is difficult to verify on mobile, and that we want to ship today, I think we should probably accept this bug as verified. Any objections?
(In reply to Lawrence Mandel [:lmandel] (use needinfo) from comment #48)
> Given that this was verified on desktop, is a platform fix, is difficult to
> verify on mobile, and that we want to ship today, I think we should probably
> accept this bug as verified. Any objections?

Yes, I think that's fine.
(In reply to Lawrence Mandel [:lmandel] (use needinfo) from comment #45)
> Just confirmed with nalexander that we only ship pdf.js in Fennec Nightly.

We don't ship pdf.js on any channel on Android. There was a period when we did but that was years ago. None of the prefs for pdf.js are present on Nightly Android. Greping the apk for pdfjs or pdf.js turns up no results. Where as greping for the strings on nightly desktop returns results.
Whiteboard: [adv-main37+][adv-esr31.6+]
Flags: needinfo?(dveditz)
Reproduced on Fx 37.0b4 under Win 7 x64 - with the .html file from comment 1 and common.js from .zip file, I get the following results: the iframe is empty, Total time taken is 0.381 s and a cmd window is launched.
Browser console output:

> ReferenceError: FirefoxCom is not defined l10n.js:100:4
> ReferenceError: MessageChannel is not defined svg>:1:0
> Error: Permission denied to access property "wrappedJSObject" svg>:1:0

Verified as fixed under Windows 7 x64, OS X 10.9.5 and Ubuntu 14.04 x32 :
- Total time taken is empty, no cmd window, iframe not empty
- Browser console output for Fx 37.0 build 2 (20150326190726), latest Aurora 38.0a2 (from 2015-03-29) and Nightly 39.0a1 (from 2015-03-29) e10s on/off:

> ReferenceError: FirefoxCom is not defined l10n.js:100:4
> ReferenceError: MessageChannel is not defined svg>:1:0
> "An error occurred while loading the PDF.
> PDF.js v1.1.24 (build: f6a8110)
> Message: undefined" viewer.js:6023

- Browser console output for ESR 31.6.0 build 2 (20150325203137)
 
> ReferenceError: FirefoxCom is not defined l10n.js:100
> ReferenceError: MessageChannel is not defined svg>:1
> "Error: stream must have data" pdf.worker.js:215
> "assert@resource://pdf.js/build/pdf.worker.js:232:5
> init@resource://pdf.js/build/pdf.worker.js:4615:5
> PDFDocument@resource://pdf.js/build/pdf.worker.js:4606:7
> LocalPdfManager@resource://pdf.js/build/pdf.worker.js:4201:5
> getPdfManager@resource://pdf.js/build/pdf.worker.js:36831:11
> wphSetupDoc@resource://pdf.js/build/pdf.worker.js:36997:7
> messageHandlerComObjOnMessage@resource://pdf.js/build/pdf.worker.js:1115:9
> " pdf.worker.js:217
> "Warning: Unsupported feature "unknown"" pdf.worker.js:200
> "Warning: Unsupported feature "unknown"" pdf.js:200
> "An error occurred while loading the PDF.
> PDF.js v1.0.68 (build: ead4cbf)

Is this enough to call this verified? Does the console output look to you?
Flags: needinfo?(bzbarsky)
You should be seeing messages (perhaps in the web console, not the browser console?) about "Security Error: Content at resource://... may not load or link to chrome://..." or so.  At least after the fix.  Are you not seeing those?

I guess it's possible that with the cross-origin bits fixed (in a different bug) that testcase no longer even reaches the code that was changed in this bug...
Flags: needinfo?(bzbarsky)
Unfortunately, I did not see any security error via the web console nor the browser
console. The only difference between a broken build and a fixed one is what I mentioned in comment 51.

Is it a must for this error to show up or the results I got are enough?
Flags: needinfo?(bzbarsky)
It really depends on which exact builds you're testing and what patches they have in them.  If the post-fix build has the patch for bug 1144988 in it, you won't even reach the code this bug modified using the testcase in this bug.

Here's a good way to verify this bug directly without interference from bug 1144988:

1)  Load resource://gre/modules/Services.jsm in Firefox.
2)  Open the web console (Tools > Web Developer > Web Console).
3)  Execute the following code in the console:

  var i = document.createElement("iframe"); i.src = "chrome://browser/content/browser.xul"; document.body.insertBefore(i, document.body.firstChild)

With this bug fixed, the iframe should stay blank and the browser console should show:

  Security Error: Content at resource://gre/modules/Services.jsm may not load or link to chrome://browser/content/browser.xul.

Without this bug fixed, there will be no security error like that, and the iframe will contain a (broken) version of the Firefox UI.
Flags: needinfo?(bzbarsky)
Thanks! 
Verified as fixed with Firefox 31.6.0 ESR build 2, Firefox 37.0 build 2, Firefox 38 beta 1 and latest Aurora 39.0a2 under Windows 7 x64, OS X 10.9.5 & Ubuntu 14.04 x32 - security error is present in Browser console with str from comment 54
No error on Firefox 37 beta 4 with the same steps.
Reproduced with the steps from comment 54 using Firefox 37 beta 6.
Verified as fixed using Firefox 38.0ESR under Win 8 32-bit, Ubuntu 12.04 32-bit and Mac OS X 10.9.5.

Marking as verified based on this. Please let me know if other verification is also needed.
Group: core-security → core-security-release
Group: core-security-release
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: