Closed
Bug 1430974
Opened 7 years ago
Closed 7 years ago
Stored XSS in chrome://browser/content/browser-media.js line 40
Categories
(Firefox :: General, defect)
Tracking
()
RESOLVED
FIXED
Firefox 59
People
(Reporter: francois.lajeunesse.robert, Assigned: Gijs)
References
Details
(Keywords: sec-moderate, Whiteboard: [post-critsmash-triage][adv-main59+])
Attachments
(1 file, 1 obsolete file)
6.07 KB,
patch
|
florian
:
review+
|
Details | Diff | Splinter Review |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0
Build ID: 20180103231032
Steps to reproduce:
Like for BUG 1430511, setting the value of the app.support.baseURL preference to include HTML content will cause an XSS issue in line 40 of chrome://browser/content/browser-media.js.
Actual results:
Whenever a EME video player plugins sends a cdm-disabled message to Firefox, the HTML content generated at line line 40 of chrome://browser/content/browser-media.js is showned in a notification popup. Therefore, any malicious content in the HTML code be executed including JavaScript (executed has privileged js ?!?!).
Moreover, since :
1- A cdm-disabled message is triggered whenever a user is trying to play DRM while CDM plugging is disabled ;
2- Disabling CDM can be performed by writing to the prefs.js (user_pref("media.gmp-widevinecdm.enabled", false);)
The malicious content execution could be triggered simply visiting a Web site offfering DRM content.
Expected results:
The value of app.support.baseURL should be sanatized prior to be inserted in HTML content at line 40 of chrome://browser/content/browser-media.js.
Assignee | ||
Updated•7 years ago
|
Component: Untriaged → General
Assignee | ||
Updated•7 years ago
|
Assignee: nobody → gijskruitbosch+bugs
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Comment 1•7 years ago
|
||
Thank you for finding and reporting those bugs, FLR.
This one looks like a sec-moderate (similar to bug 1430511), as it's limited to local attackers.
But do keep looking, I'm sure you'll get there ;)
Keywords: sec-moderate
Assignee | ||
Comment 2•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Attachment #8943192 -
Attachment description: , → Patch v0.1
Assignee | ||
Updated•7 years ago
|
Attachment #8943192 -
Flags: review?(florian)
Comment 3•7 years ago
|
||
Comment on attachment 8943192 [details] [diff] [review]
Patch v0.1
Review of attachment 8943192 [details] [diff] [review]:
-----------------------------------------------------------------
This (especially the getFormattedString partial reimplementation in JS) seems to add more complexity than this is worth.
::: browser/base/content/browser-media.js
@@ +35,5 @@
> return true;
> },
> getLearnMoreLink(msgId) {
> let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel");
> let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
I'm not sure I understand the threat correctly here, but could we just do something like:
try {
if (!Services.io.newURI(baseURL).schemeIs("https"))
throw;
} catch(e) {
Cu.reportError("invalid app.support.baseURL");
return "";
}
Should we check that the url is valid directly inside Services.urlFormatter? It seems we have plenty of callers, and some may also insert the url directly into the DOM without sanitization.
@@ +110,5 @@
> + let message = gNavigatorBundle.getString(msgId);
> + if (!labelParams.length) {
> + message = [message];
> + } else {
> + message = message.split(/%(?:\$\d)?S/);
Splitting on eg. %$2S without recording the position (2) means we may be swapping the order of the variables if some localized strings don't display the variables in the same order as the en-US string.
Attachment #8943192 -
Flags: review?(florian) → review-
Assignee | ||
Comment 4•7 years ago
|
||
(In reply to Florian Quèze [:florian] from comment #3)
> Comment on attachment 8943192 [details] [diff] [review]
> Patch v0.1
>
> Review of attachment 8943192 [details] [diff] [review]:
> -----------------------------------------------------------------
>
> This (especially the getFormattedString partial reimplementation in JS)
> seems to add more complexity than this is worth.
I disagree. The complexity will go away with fluent anyway, but we should kill the innerHTML stuff with fire.
> ::: browser/base/content/browser-media.js
> @@ +35,5 @@
> > return true;
> > },
> > getLearnMoreLink(msgId) {
> > let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel");
> > let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
>
> I'm not sure I understand the threat correctly here, but could we just do
> something like:
> try {
> if (!Services.io.newURI(baseURL).schemeIs("https"))
> throw;
> } catch(e) {
> Cu.reportError("invalid app.support.baseURL");
> return "";
> }
We could, but I just really don't think we should be assigning to innerHTML, full stop. app.support.baseURL is only one of many issues.
> Should we check that the url is valid directly inside Services.urlFormatter?
> It seems we have plenty of callers, and some may also insert the url
> directly into the DOM without sanitization.
I guess we could. I'm nervous about breaking the entirety of the prefs when l10n or whatever mis-specifies the URL. Right now, the link would be broken but there'd be no other ill effects.
> @@ +110,5 @@
> > + let message = gNavigatorBundle.getString(msgId);
> > + if (!labelParams.length) {
> > + message = [message];
> > + } else {
> > + message = message.split(/%(?:\$\d)?S/);
>
> Splitting on eg. %$2S without recording the position (2) means we may be
> swapping the order of the variables if some localized strings don't display
> the variables in the same order as the en-US string.
That would be an issue if there was ever more than 1 replacement item, and there isn't.
Flags: needinfo?(florian)
Assignee | ||
Comment 5•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Attachment #8943192 -
Attachment is obsolete: true
Assignee | ||
Comment 6•7 years ago
|
||
Comment on attachment 8943292 [details] [diff] [review]
Patch v0.2
>diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js
> case "cdm-insufficient-version":
> notificationId = "drmContentCDMInsufficientVersion";
>- params = [this._brandShortName];
>+ notificationMessage = this.getMessageWithBrandName(notificationId);
> break;
>
> case "cdm-not-installed":
> notificationId = "drmContentCDMInstalling";
>- params = [this._brandShortName];
>+ notificationMessage = this.getMessageWithBrandName(notificationId);
> break;
FWIW, I tried to look at removing this duplication but couldn't think of a reasonable solution. We could remove these lines and then add:
if (!notificationMessage) {
notificationMessage = this.getMessageWithBrandName(notificationId);
}
but that would possibly surprise future consumers and actually adds lines, so I decided not to do that.
Attachment #8943292 -
Attachment description: , → Patch v0.1
Attachment #8943292 -
Flags: review?(florian)
Assignee | ||
Updated•7 years ago
|
Attachment #8943292 -
Attachment description: Patch v0.1 → Patch v0.2
Assignee | ||
Updated•7 years ago
|
Flags: needinfo?(florian)
Comment 7•7 years ago
|
||
Comment on attachment 8943292 [details] [diff] [review]
Patch v0.2
Review of attachment 8943292 [details] [diff] [review]:
-----------------------------------------------------------------
Thanks for updating the patch, looks much better now. :-)
Attachment #8943292 -
Flags: review?(florian) → review+
Assignee | ||
Comment 8•7 years ago
|
||
Assignee | ||
Comment 9•7 years ago
|
||
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
status-firefox57:
--- → wontfix
status-firefox58:
--- → wontfix
status-firefox59:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → Firefox 59
Assignee | ||
Updated•7 years ago
|
Group: firefox-core-security → core-security-release
Updated•7 years ago
|
status-firefox-esr52:
--- → wontfix
Updated•7 years ago
|
Flags: qe-verify-
Whiteboard: [post-critsmash-triage]
Updated•7 years ago
|
Whiteboard: [post-critsmash-triage] → [post-critsmash-triage][adv-main59+]
Updated•6 years ago
|
Group: core-security-release
You need to log in
before you can comment on or make changes to this bug.
Description
•