Closed
Bug 1320039
(CVE-2016-9902)
Opened 8 years ago
Closed 8 years ago
Pocket extension unnecessarily exposes its messaging interface to web pages
Categories
(Firefox :: Pocket, defect)
Firefox
Pocket
Tracking
()
People
(Reporter: jwkbugzilla, Assigned: Gijs)
Details
(Keywords: csectype-priv-escalation, reporter-external, sec-moderate, Whiteboard: [adv-main50.1+][adv-esr45.6+])
Attachments
(3 files, 2 obsolete files)
857 bytes,
text/html
|
Details | |
10.54 KB,
patch
|
jwkbugzilla
:
review+
kmag
:
review+
gchang
:
approval-mozilla-aurora+
gchang
:
approval-mozilla-beta+
ritu
:
approval-mozilla-release+
lizzard
:
approval-mozilla-esr45-
|
Details | Diff | Splinter Review |
9.43 KB,
patch
|
Details | Diff | Splinter Review |
Note: I am reporting this issue here rather than to Pocket because Pocket is an integral part of Firefox and cannot be disabled or removed by regular means.
The bubble displayed by the Pocket toolbar button is actually an <iframe> loading from either about:pocket-signup or about:pocket-saved. In order to communicate with that frame the Pocket extension registers event listeners on browser.xul's document, accepting untrusted events. The event listeners don't do anything to verify the origin of the event so that events bubbling up from the browser's content area will be processed as well.
Steps to reproduce (I tested with Firefox 53.0a1 nightly 2016-11-23 on macOS 10.12):
1. Make sure that E10S is disabled (with E10S events from content won't bubble up to the browser).
2. Click the Pocket button to make sure that the extension is initialized. It doesn't matter whether anything happens after that, you don't need to sign up with Pocket.
3. Now open the attached webpage in Firefox and click the "Open about:preferences with Sync tab selected".
This button will open about:preferences#sync page, something that web pages normally cannot do. Pop-up blocker doesn't affect this, so websites can open any number of pop-ups at any time this way. Security checks don't apply either so opening arbitrary file:///, chrome:// or about: URLs is possible.
Note that this only abuses "openTabWithUrl" message that Pocket listens to. There is a number of other message listeners which might also have abuse potential - e.g. "deleteItem" message allows deleting items from Pocket. Note also that the website can detect when its attack was successful because the Pocket extension will remove the event target from the page.
Also, this issue is completely avoidable. There is only one Pocket frame in the browser document, the event listeners could be registered directly on that iframe element rather than on the document - this would make sure that no events from other sources will be received.
Assignee | ||
Comment 1•8 years ago
|
||
(In reply to Wladimir Palant from comment #0)
> Created attachment 8814034 [details]
> Proof of concept webpage
>
> Note: I am reporting this issue here rather than to Pocket because Pocket is
> an integral part of Firefox and cannot be disabled or removed by regular
> means.
Eh, fairly sure that you can just right click the pocket button, click 'remove from toolbar', and that should stop all of this (if not immediately, certainly on the next restart). Also, most of this code was still written by pocket...
Shane, can you make sure we CC whoever needs to be CC'd from the pocket side on this?
> The bubble displayed by the Pocket toolbar button is actually an <iframe>
> loading from either about:pocket-signup or about:pocket-saved. In order to
> communicate with that frame the Pocket extension registers event listeners
> on browser.xul's document, accepting untrusted events. The event listeners
> don't do anything to verify the origin of the event so that events bubbling
> up from the browser's content area will be processed as well.
Ugggh.
Flags: needinfo?(mixedpuppy)
Reporter | ||
Comment 2•8 years ago
|
||
Well, if you never click the Pocket button it will never initialize and my PoC won't work. But if you click it, and be it out of curiosity - removing it from the toolbar will no longer help you, for the current session you will be vulnerable.
Assignee | ||
Comment 3•8 years ago
|
||
This time, actual origin principal checks against about:pocket-signup/saved *and* restricting the message listeners to the iframe. Mike, can you check that this is sufficient and that I haven't broken anything (looking briefly, it seems OK to me, but...).
Attachment #8814048 -
Flags: review?(mozilla)
Assignee | ||
Comment 4•8 years ago
|
||
(In reply to :Gijs Kruitbosch from comment #3)
> Created attachment 8814048 [details] [diff] [review]
> Patch v0.1
>
> This time, actual origin principal checks against about:pocket-signup/saved
> *and* restricting the message listeners to the iframe. Mike, can you check
> that this is sufficient and that I haven't broken anything (looking briefly,
> it seems OK to me, but...).
I'm assuming I don't need to touch messages.js because it only runs *inside* the iframes for messages/events going in the other direction. That said, I wonder if you could frame those documents using their chrome URIs and then manipulate them that way :| .
Reporter | ||
Comment 5•8 years ago
|
||
(In reply to :Gijs Kruitbosch from comment #4)
> That said, I
> wonder if you could frame those documents using their chrome URIs and then
> manipulate them that way :| .
Given bug 1320057 it's probably a good thing that they are accessed via about: URIs that drop all privileges.
Note that changing removeMessageListener() is pointless - it is dead code not being called anywhere and it wouldn't work anyway (it removes the wrong function, not the closure added in addMessageListener). There is also quite a bit of unnecessary complexity in the surrounding code but that's irrelevant for this security issue.
Assignee | ||
Comment 6•8 years ago
|
||
We might as well make it impossible for it to open URLs it couldn't otherwise open itself in its own iframe, for defense in depth purposes.
Assignee: nobody → gijskruitbosch+bugs
Attachment #8814048 -
Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #8814048 -
Flags: review?(mozilla)
Assignee | ||
Comment 7•8 years ago
|
||
(In reply to Wladimir Palant from comment #5)
> (In reply to :Gijs Kruitbosch from comment #4)
> > That said, I
> > wonder if you could frame those documents using their chrome URIs and then
> > manipulate them that way :| .
>
> Given bug 1320057 it's probably a good thing that they are accessed via
> about: URIs that drop all privileges.
They are in the iframe we use for the actual UI. But the pages have chrome:// URLs, e.g. chrome://pocket/content/panels/saved.html . They're contentaccessible too, presumably in order for the about: pages to be able to load all the other gunk. That still doesn't let you link to them, fortunately, and AIUI this vulnerability doesn't let you open URLs into arbitrary subframes - "just" in new tabs, which at least avoids then being able to spoof the messages back to these pages (like, say, the suggested tags) which you could then exploit to go other places in the now-system-privileged page you just opened. :|
Assignee | ||
Comment 8•8 years ago
|
||
(though also, I think/hope that we don't allow system-privileged frames inside content-privileged documents)
Assignee | ||
Comment 9•8 years ago
|
||
If it's unused, let's just take it out, then.
Attachment #8814074 -
Attachment is obsolete: true
Attachment #8814076 -
Flags: review?(trev.moz)
Attachment #8814076 -
Flags: review?(mozilla)
Reporter | ||
Comment 10•8 years ago
|
||
(In reply to :Gijs Kruitbosch from comment #8)
> (though also, I think/hope that we don't allow system-privileged frames
> inside content-privileged documents)
I'm pretty sure that this is possible as long as a system-privileged script sets location.href.
Reporter | ||
Comment 11•8 years ago
|
||
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
Review of attachment 8814076 [details] [diff] [review]:
-----------------------------------------------------------------
::: browser/extensions/pocket/content/main.js
@@ +364,5 @@
> // Open a new tab with a given url and activate if
> var _openTabWithUrlMessageId = "openTabWithUrl";
> + pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) {
> + try {
> + urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
Given that this is technically an extension and that the code is probably upstreamed to Pocket, is it a good idea to rely on implementation details like the global urlSecurityCheck function? Besides, just calling scriptSecurityManager directly wouldn't be significantly longer:
var secMan = Services.scriptSecurityManager;
secMan.checkLoadURIStrWithPrincipal(data.url, contentPrincipal, secMan.DISALLOW_INHERIT_PRINCIPAL);
Assignee | ||
Comment 12•8 years ago
|
||
(In reply to Wladimir Palant from comment #10)
> (In reply to :Gijs Kruitbosch from comment #8)
> > (though also, I think/hope that we don't allow system-privileged frames
> > inside content-privileged documents)
>
> I'm pretty sure that this is possible as long as a system-privileged script
> sets location.href.
Hrmpf. Will file an orthogonal bug about that.
Updated•8 years ago
|
Flags: needinfo?(mixedpuppy)
Assignee | ||
Comment 13•8 years ago
|
||
(In reply to Wladimir Palant from comment #11)
> Comment on attachment 8814076 [details] [diff] [review]
> Patch v0.3
>
> Review of attachment 8814076 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> ::: browser/extensions/pocket/content/main.js
> @@ +364,5 @@
> > // Open a new tab with a given url and activate if
> > var _openTabWithUrlMessageId = "openTabWithUrl";
> > + pktUIMessaging.addMessageListener(iframe, _openTabWithUrlMessageId, function(panelId, data, contentPrincipal) {
> > + try {
> > + urlSecurityCheck(data.url, contentPrincipal, Services.scriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
>
> Given that this is technically an extension and that the code is probably
> upstreamed to Pocket, is it a good idea to rely on implementation details
> like the global urlSecurityCheck function?
It also relies on openUILink / openLinkIn, I think? Which is in the same file. So I don't think that relying on this as well is fine.
Assignee | ||
Comment 14•8 years ago
|
||
(In reply to :Gijs Kruitbosch from comment #13)
> It also relies on openUILink / openLinkIn, I think? Which is in the same
> file. So I don't think that relying on this as well is fine.
Eh, too many negations. But yeah, I think this is fine, tbh.
Updated•8 years ago
|
Attachment #8814076 -
Flags: review+
Reporter | ||
Comment 15•8 years ago
|
||
(In reply to :Gijs Kruitbosch from comment #13)
> It also relies on openUILink / openLinkIn, I think? Which is in the same
> file. So I don't think that relying on this as well is fine.
Not actually the same thing - it's in the same file now because it moved there. This is documented API (https://developer.mozilla.org/de/docs/Codeschnipsel/Tabbed_browser#Opening_a_URL_in_the_correct_window.2Ftab) and has been stable for a long time. Quite a few extensions rely on it already which is probably why it is still around in that form. urlSecurityCheck() is neither old nor documented.
Comment 16•8 years ago
|
||
It's documented to the extent that someone wrote a code snippet that uses it, but that says nothing about it being supported, or its use being good practice. In fact, the en-US version of that page was marked as obsolete because it suggested a lot of bad practices.
I don't think this is worth worrying about. checkLoadURIStrWithPrincipal is no more of a public API than urlSecurityCheck, and it would be much easier to make changes to the latter (which is already used by many add-ons) without breaking compatibility than it would the former.
Reporter | ||
Comment 17•8 years ago
|
||
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
Review of attachment 8814076 [details] [diff] [review]:
-----------------------------------------------------------------
Well, if everybody agrees that this function is safe to use from an extension...
Attachment #8814076 -
Flags: review?(trev.moz) → review+
Comment 18•8 years ago
|
||
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
Other folks have reviewed.
Attachment #8814076 -
Flags: review?(mozilla)
Updated•8 years ago
|
Flags: sec-bounty?
Keywords: csectype-priv-escalation,
sec-moderate
Assignee | ||
Comment 19•8 years ago
|
||
Assignee | ||
Comment 20•8 years ago
|
||
This was merged yesterday but somehow the merge didn't comment here:
https://hg.mozilla.org/mozilla-central/rev/12c2619098c3
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 53
Assignee | ||
Updated•8 years ago
|
Assignee | ||
Updated•8 years ago
|
status-firefox-esr45:
--- → affected
Assignee | ||
Updated•8 years ago
|
Flags: qe-verify?
Assignee | ||
Comment 22•8 years ago
|
||
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
[Approval Request Comment]
If this is not a sec:{high,crit} bug, please state case for ESR consideration: sec-moderate, obvious html injection issue that might be remotely exploitable, trivial patch. I would be more sanguine about not having this on ESR if we weren't about to roll it into 50.1 giving adversaries 4 months to figure out how to exploit this together with 1320057 and other addon bugs into something higher severity (before it'll ship as part of 52esr)
User impact if declined: see above
Fix Landed on Version: 53
Risk to taking this patch (and alternatives if risky): pretty low. The changes are straightforward. We should make sure they get tested on release/beta/aurora, of course.
Approval Request Comment
[Is this code covered by automated tests?]: Some basic automated tests cover stuff this code changes, but not in any great deapth, sadly.
[Has the fix been verified in Nightly?]: not yet...
[Needs manual test from QE? If yes, steps to reproduce]:
from comment #1:
> Steps to reproduce (I tested with Firefox 53.0a1 nightly 2016-11-23 on macOS
> 10.12):
>
> 1. Make sure that E10S is disabled (with E10S events from content won't
> bubble up to the browser).
> 2. Click the Pocket button to make sure that the extension is initialized.
> It doesn't matter whether anything happens after that, you don't need to
> sign up with Pocket.
> 3. Now open the attached webpage in Firefox and click the "Open
> about:preferences with Sync tab selected".
>
> This button will open about:preferences#sync page, something that web pages
> normally cannot do.
In builds without the patch, the page will open. In builds with the patch, it shouldn't open.
The patch changes how some of the pocket internals function. The basic verification steps would amount to checking:
a) you can still successfully save pages in pocket
b) you can still tag them as you like
c) you can still remove pages once saved in pocket, as you would before.
[List of other uplifts needed for the feature/fix]: bug 1320057 is not necessary for this fix to work, but because both affect pocket and how easy it is to run code in its code, I would suggest both need uplift.
[Is the change risky?]: not very
[Why is the change risky/not risky?]: well, the worst that could happen is that we break pocket's tagging system. Manual tests by me suggests this patch doesn't do that. It's also pretty straightforward.
Attachment #8814076 -
Flags: approval-mozilla-release?
Attachment #8814076 -
Flags: approval-mozilla-esr45?
Attachment #8814076 -
Flags: approval-mozilla-beta?
Attachment #8814076 -
Flags: approval-mozilla-aurora?
Comment 23•8 years ago
|
||
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
Fix a sec-moderate related to pocket. Beta51+ and Auror52+. Should be in 51 beta 6.
Attachment #8814076 -
Flags: approval-mozilla-beta?
Attachment #8814076 -
Flags: approval-mozilla-beta+
Attachment #8814076 -
Flags: approval-mozilla-aurora?
Attachment #8814076 -
Flags: approval-mozilla-aurora+
Comment 24•8 years ago
|
||
tracking-firefox50:
--- → ?
tracking-firefox51:
--- → ?
tracking-firefox52:
--- → ?
tracking-firefox53:
--- → ?
tracking-firefox-esr45:
--- → ?
Comment 25•8 years ago
|
||
Flags: needinfo?(rkothari)
Comment on attachment 8814076 [details] [diff] [review]
Patch v0.3
This meets the 50.1.0 bar, approving for esr45.6 as well.
Attachment #8814076 -
Flags: approval-mozilla-release?
Attachment #8814076 -
Flags: approval-mozilla-release+
Attachment #8814076 -
Flags: approval-mozilla-esr45?
Attachment #8814076 -
Flags: approval-mozilla-esr45+
Comment 27•8 years ago
|
||
I don't think Pocket shipped with ESR45 (I don't see it in the extensions code)
Updated•8 years ago
|
Attachment #8814076 -
Flags: approval-mozilla-esr45+ → approval-mozilla-esr45-
Comment 28•8 years ago
|
||
Comment 29•8 years ago
|
||
ESR45 is affected after all.
Comment 30•8 years ago
|
||
uplift |
Comment 31•8 years ago
|
||
We verified this along with some spot checks on the affected areas on the following builds:
Fx 50.1.0 tinderbox, 45.5.2 ESR tinderbox, 51b6, 52.0a2 (2016-12-05), 53.0a1 (2016-12-06).
More details here: https://public.etherpad-mozilla.org/p/pocket-security-testing
No issues were found, marking as verified fixed.
Status: RESOLVED → VERIFIED
Flags: qe-verify?
Comment 32•8 years ago
|
||
This needs to be added to the 50.1 Firefox advisory and ESR 45.5.2 (or 45.6 since I don't think there is a 45.5.2 ESR release) after it ships in ESR.
Flags: needinfo?(dveditz)
Flags: needinfo?(abillings)
Comment 33•8 years ago
|
||
Ok. My mistake, there is a 45.6 release so this can be added once that ships.
Updated•8 years ago
|
Flags: needinfo?(abillings)
Whiteboard: [adv-main50.1+][adv-esr45.6+]
Updated•8 years ago
|
Alias: CVE-2016-9902
Updated•8 years ago
|
Flags: needinfo?(dveditz)
Updated•8 years ago
|
Group: firefox-core-security → core-security-release
Updated•8 years ago
|
Flags: sec-bounty? → sec-bounty+
Updated•8 years ago
|
Group: core-security-release
Updated•9 months ago
|
Keywords: reporter-external
You need to log in
before you can comment on or make changes to this bug.
Description
•