Closed Bug 1287590 Opened 8 years ago Closed 4 years ago

Webpage can override WebExtension frames

Categories

(Developer Documentation Graveyard :: Add-ons, defect)

defect
Not set
normal

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: andy+bugzilla, Unassigned)

Details

(Whiteboard: [design-decision-needed])

This is based on an email thread, which points to a github discussion:

https://github.com/mdn/webextensions-examples/issues/74

I thought it would make sense to file a bug on that to see if this is something we should work on.

rgh36167: "Some examples (eg inpage-toolbar-ui ) inject code into a webpage. I would assume if the webpage isn't under our control it can easily delete, obscure and otherwise manipulate the displayed iframe?"

rpl: "@rgh36167 good point

Follows an initial list of scenarios (all tried on the inpage-toolbar-ui example), which can be helpful to put together a similar list on MDN to help an add-on developer to evaluate the security implications of the features he is planning to use in its add-on.

The web page currently can:

* remove the iframe completely (and eventually inject another one)
* hide the iframe by applying styles to the iframe element
* update the src attribute of the iframe to a "data:" url or an "https:" url (if the remote url doesn't prevent its loading into an iframe)
* update the src attribute of the iframe with the same url with the changes on the hash and search component (no reloading happens, but the new hash and search component seems to be available in the iframe)

The web page currently is not able to:

* use iframe.contentWindow.eval to execute javascript code with the privileges and API of the inject (raise security errors)
* access the document loaded in the injected iframe and its DOM elements (raise security errors)
* update the src with an arbitrary "moz-extension:" url (security error and no loading happens in the iframe)"
Component: WebExtensions → Add-ons
Product: Toolkit → Developer Documentation
Version: 48 Branch → unspecified
Moved because you feel this is a documentation issue to explain the difference, rather than something we should try to address?
Oh, sorry, I misread and thought you were asking for documentation.

This isn't something we can do anything about, really. Content pages are hostile territory. The best we can do is try to make developers aware of the potential problems.
I see considerable risk that addon developers will try to use this and similar as replacement for SDK-addons pannel and other ui elements. I can't think of any safe way to use inpage-ui-toolbar (and similar) for something useful so they should be deprecated wholeheartedly. The examples should be left there with a big fat note "DONT DO IT LIKE THAT".

browseractions has popups which could be a full and safe replacement for SDK/pannel *if* they could be triggered programmatically instead of having the requirement to be explicitly user activated by a toolbar button. 
It would appear that internally some kind of Popup.show() must already exist and having it exported to the API would be a trivial change?
Thanks for raising this, and thanks to :rpl for the detailed analysis.

I'd like to know what Andy and Kris think of comment 3. Should we deprecate this technique, or document it as a possible way to implement a UI, and document the security considerations?

I can have a go at writing up Luca's analysis. I'm not 100% sure where would be best, perhaps in the content scripts guide: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts. Then I could add a note in the README for this example, pointing back at that.
Flags: needinfo?(amckay)
Yeah, I'm inclined to agree that we shouldn't be encouraging this. If we want extensions to include toolbars, we should give them an API that lets them do it properly.
An explicit API would be nice and avoid the conflict of who is right: the add-on or the page author. Although as dveditz says in bug 1267027 comment 3, we should probably trust the add-on.

I don't know if its a huge priority for anyone at this time, so this bug might be around for a while (unless someone jumps on it) and should probably be documented until we fix it. I can't think of a better page than the content scripts right now.
Flags: needinfo?(amckay)
There is browserAction.openPopup(), which is implemented as an internal function in Chrome:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/browserAction/openPopup
(In reply to Andy McKay [:andym] from comment #6)
> An explicit API would be nice and avoid the conflict of who is right: the
> add-on or the page author. Although as dveditz says in bug 1267027 comment
> 3, we should probably trust the add-on.

we can't trust them too much in this case because for years the documentation
of content scripts was suggesting that they run on a sandboxed version of DOM:
"if a page script has redefined the behavior of some DOM object, the content 
 script sees the original behavior."

This obviously refers to javascript code and not DOM tree structure but
may not be obvious for everyone.
I have seen addons which do naively insert their UI elements into the DOM 
tree and would be more or less seriously broken if the page sabotages
them by accident or intentionally. Example:
I completely agree that injecting an iframe into the page cannot be considered the "safe way" to overlay addon ui to a web page, at least not safe enough to be considered a reasonable approach to use over arbitrary and potentially hostile pages.

In my opinion there is only one kind of in-page ui that can opt to use this as a reasonable strategy: addons that implements in-page developer utilities that inject their ui into trusted pages (trusted because most of the times are pages created from the user of the addon itself).

(e.g. some of the devtools add-ons inject into the target web pages this kind of UI elements, to highlight something or overlay more information to it)
(In reply to Will Bamberg [:wbamberg] from comment #7)
> There is browserAction.openPopup(), which is implemented as an internal
> function in Chrome:
> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/browserAction/
> openPopup

having that would certainly help a lot.

There remain cases like https://addons.mozilla.org/en-US/android/addon/quick-gestures
and https://addons.mozilla.org/en-US/android/addon/pagedown-pageup-buttons/ which
need something else to do their trick.
Until a notification/toolbar API exists, I plan to use a content script to inject exactly such an iframe:

https://github.com/mozilla/blok

The target web pages could very well be hostile (to a tracking/ad-blocker) and so they could remove or hide my iframe, or change the src of the iframe.

In my case, this breaks the UI, but not the underlying tracking-blocking functionality.

So for now, I'll continue with my iframe until I suspect hostile sites are doing this and targeting my add-on specifically.
No longer blocks: webext-popups
I'm an add-on developer, simply wanting to programmatically display some information to a user, regardless of what page they are on, more significant than a badge, not pinned to a specific browser location like the browser action popup, but like that popup, allow myself full control over the page, without worrying about what a content page might do.

There was no way to do this that I could see in the MDN WebExtensions API, so I was trying to use the iframe technique.

(In reply to Kris Maglione [:kmag] from comment #5)
> Yeah, I'm inclined to agree that we shouldn't be encouraging this. If we
> want extensions to include toolbars, we should give them an API that lets
> them do it properly.

<sarcasm>Funny, it's too bad there was never any toolbar set aside for add-ons.[1]  It's not like such a useful feature would ever be removed.  It would be surprising if such a short-sighted thing ever occurred.  But if it did, I'm sure a XUL/Overlay-only add-on like The Addon Bar (Restored)[sic][2] would be incredibly useful in a WebExtension-only ecosystem, with no XUL or XPCOM.</sarcasm>

Ok, in all seriousness.  I'm guessing that's not exactly the sort of toolbar Kris was referring to.  The old add-on bar was limited to a single-row of icons (I never did actually manage to fill it to see if it stacked to 2+ icons high).  But it was a common place here add-on developers could post some sort of interface without worrying about content page interference.

And in contrast, trying to it all my current icons into the navigation menu is rather insane.  It leaves the UI completely cluttered and cramped!  I actually go out of my way to remove most buttons from nav bar, so I can see the full URL.  Also, my hand, and my eyes, are almost never focused on the upper-right corner.  It's never convenient to move there.  My mouse and eyes are usually somewhere in the middle of a page, with the top part of browser out of the central vision, yet the lower-half of browser remains in sight.

Maybe this varies for some people, but that reinforces my point: there is a need to notify users in a way which THEY can configure.  Not force the upper-right (look for a badge, click a button, restricted to a popup attached to that button), nor the lower-right (legacy add-ons bar).

(In reply to Andy McKay [:andym] from comment #6)
> An explicit API would be nice and avoid the conflict of who is right: the
> add-on or the page author. Although as dveditz says in bug 1267027 comment
> 3, we should probably trust the add-on.

In many cases, probably nobody is "right".  The page author may be malicious (safe to always assume), - or at least sloppy - and the developer may be (is likely to be) naive or misinformed, and likewise may be sloppy.  Whereas Mozilla reviews hosted add-ons, and it does not review all the webpages that exist, have existed, or will yet exist, everywhere else, for all time, I tend to think that the add-on should be given the right.

Notice the distinction between BEING right, and being GRANTED the right.  Ah, the ambiguity of the English language.  In other words, a developer may not be using the "correct" code technique, but given a dispute between competing instructions, they should be granted the "power" to override the content.  If the add-on breaks pages, then it's up to the developer to fix the problem (possibly with hints from validation tools or training reviewers to spot dangerous anti-patterns), whereas if some random page is breaking an add-on (intentional or not), they're under absolutely no obligation to fix anything.

> I don't know if its a huge priority for anyone at this time, so this bug
> might be around for a while (unless someone jumps on it) and should probably
> be documented until we fix it. I can't think of a better page than the
> content scripts right now.

With the amount of StackOverflow questions relating to using iframes, this might be classified as a precursor to an "epidemic" waiting to happen.  If I were to put on my grey hat, I'd analyze all freely-downloadable WebExtensions add-ons with an automated tool, determine which use a vulnerability such as this, and more importantly, if the background is talking to this iframe and acting on information, craft patterns to sniff for, and assuming I had a backdoor to inject code on some popular sites, replace the source with identical DOM structure and graphical elements, but maybe different instructions (URLs, etc), or just hide and spoof with an overlay that transmits all information exactly, but performs a man in the middle attack by also sending a copy elsewhere for analysis.  I would not target just ONE add-on, I would target ALL OF THEM, because they are made vulnerable by a deficient API that forces developers to use unsafe practices, with the false sense of security that "my little add-on isn't a high-value target so they probably won't seek to exploit mine".

Case in point:

[:groovecoder] from comment #11)
> Until a notification/toolbar API exists, I plan to use a content script to
> inject exactly such an iframe:
[snip]
> The target web pages could very well be hostile (to a tracking/ad-blocker)
> and so they could remove or hide my iframe, or change the src of the iframe.
> 
> In my case, this breaks the UI, but not the underlying tracking-blocking
> functionality.
> 
> So for now, I'll continue with my iframe until I suspect hostile sites are
> doing this and targeting my add-on specifically.

But beyond any technological attacks, the presence of this vulnerability opens up social attacks.  The trust in an add-on can be eroded (for the add-on, add-on developer, the web site, the browser) if  spoofed and does distasteful things, and the technological distinction between "add-on developer", "API limitation" and "malicious website", have no meaning whatsoever to the average user.  The user puts their trust in the add-on developer, and if bad things happen, they get the blame.  The add-on developer may try to make excuses and pass the blame to the browser, and share it with the API, and point at online forums that said "well, we probably don't have to worry about it", but the add-on developer is the last person in the chain to the user, the last person who made a conscious decision to do something unsafe.  And they are pressured to do unsafe things by users who want features to make life easier and more comfortable, but don't want to think about or are unable to understand the consequences.

Some have suggested avoiding iframe usage entirely, in favor of the Shadow DOM technique, which I have only just begun to research, though I don't see how this fundamentally differs, as it still relies upon injecting an element into content page.  Even if the shadowed DOM is encapsulated, the root element could still be fiddled.  Any comments to feasibility of this technique, how hardened it is against exploitation, or further reading or code examples, would be helpful.  Nothing I've read really explains the technique in a way I can understand or visualize.

[1] https://support.mozilla.org/en-US/kb/what-happened-to-the-add-on-bar
[2] https://addons.mozilla.org/en-US/firefox/addon/the-addon-bar/(In reply to Luke Crouch
(In reply to Leif-AMO from comment #12)
> I'm an add-on developer, simply wanting to programmatically display some
> information to a user, regardless of what page they are on, more significant
> than a badge, not pinned to a specific browser location like the browser
> action popup, but like that popup, allow myself full control over the page,
> without worrying about what a content page might do.

The injected iframe has been provided mostly for cross-browser compatibility reasons (and because Chrome doesn't have, and probably is not going to have in the near future, any sidebar or toolbar APIs).  

Nevertheless, there are other API in work that are going to provide better and safer alternatives on Firefox:

- Bug 1208596 - Implement sidebar extension point (which is probably going to be compatible with the sidebarAPI provided by Opera)
- Bug 1215064 - Design and implement an API for Toolbars
Anything new? Did some new safe API to display popups emerge? Did anyone with the powers to grep all addons have a look and tried to identify how many of those inject iframes or other UI elements in potentially dangerous ways? Is it planned to scan addons for such vulnerabilities?
To follow-up on a discussion we are having from mobile-firefox-dev@ [1], Prompt.jsm [2] allowed add-on developers to create custom native prompts on mobile but there doesn't seem to be a valid replacement (`alert`, `prompt`, etc. are too minimal). Injecting custom HTML seems to be the closest substitute but this bug is an issue.

[1]: https://mail.mozilla.org/pipermail/mobile-firefox-dev/2017-August/002283.html
[2]: https://developer.mozilla.org/en-US/Add-ons/Legacy_Firefox_for_Android/API/Prompt.jsm
> Injecting custom HTML seems to be the closest substitute but this bug is an issue.

As I mentioned in the mailing list, I believe this bug is specifically about injecting iframes, not all HTML. You can create your own prompts with DIVs--iframes are not needed.
(In reply to Eric Jung [:ericjung] from comment #16)
> > Injecting custom HTML seems to be the closest substitute but this bug is an issue.
> 
> As I mentioned in the mailing list, I believe this bug is specifically about
> injecting iframes, not all HTML. You can create your own prompts with
> DIVs--iframes are not needed.

And it would be even worse than using IFrames, since not only your prompts would be exactly as spoofable (which seems to be the whole point of this bug), but their content would also be fully readable by the hosting (and potentially hostile) web page.
MDN Web Docs' bug reporting has now moved to GitHub. From now on, please file content bugs at https://github.com/mdn/sprints/issues/ and platform bugs at https://github.com/mdn/kuma/issues/.
Status: NEW → RESOLVED
Closed: 4 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.