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

Issue 746517 link

Starred by 3 users

Issue metadata

Status: Fixed
Owner:
Closed: Aug 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux
Pri: 1
Type: Bug-Security



Sign in to add a comment

alert() titles from apps leak to webpages in the same process

Reported by anowlcal...@gmail.com, Jul 19 2017

Issue description

UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36

Steps to reproduce the problem:
1. Install the Inbox by Gmail app (https://chrome.google.com/webstore/detail/inbox-by-gmail/pkclgpgponpjmpfokoepglboejdobkpl).
2. Open the app or go to inbox.google.com.
3. Run alert() in the console and observe that the title is "Inbox by Gmail". (If it isn't, the Inbox app isn't installed.)
4. Middle-click a link in Inbox to open an external site in a new tab.
5. Run alert() in the new tab and observe that the title is still "Inbox by Gmail", even though the website is not Inbox.

What is the expected behavior?
Normal webpages should have an alert title like "example.com says:".

What went wrong?
If a website is running in the same process as an app, the website's alerts will inherit the app's alert title.  Here, the external webpage gets the alert title "Inbox by Gmail", which allows it to impersonate Inbox.

Did this work before? N/A 

Chrome version: 59.0.3071.115  Channel: stable
OS Version: Ubuntu 16.04
Flash Version: 

Tested with both the Inbox and Gmail apps (with Gmail you must open the app directly, visiting gmail.com won't work).

AFAICT this is  bug 661388 , which was closed as "no repro, no hints as to what happened, no idea what's going on" over six months ago.

This only occurs when the webpage is in the same process as the app, which does not happen if the link is ctrl-clicked or clicked normally. Possibly  bug 23815  is related? Nevertheless, sharing a process with an app shouldn't affect anything about a webpage (and vice versa).
 
inbox-inherited-title.png
15.2 KB View Download
Cc: a...@chromium.org
Labels: Security_Severity-Medium Security_Impact-Stable
Owner: rdevlin....@chromium.org
Status: Assigned (was: Unconfirmed)
Devlin, are you able to reproduce this and figure out what happened in  bug 661388 ?
Cc: -a...@chromium.org rdevlin....@chromium.org creis@chromium.org nasko@chromium.org alex...@chromium.org
Owner: a...@chromium.org
Fun!

Avi is probably most qualified to take a look at this, as JS dialog master (Avi, happy to help if I can!).

I wonder if this is related to any of the hosted apps process behavior that the site isolation team has been running into - +a smattering of site isolation folks as well.

Comment 3 by a...@chromium.org, Jul 19 2017

Cc: a...@chromium.org
Owner: rdevlin....@chromium.org
The JavaScript dialog code gets the title to use for the dialog by making a call to JavaScriptDialogExtensionsClient::GetExtensionName(). If that function returns false then no special name is used, but if it returns true, then that means that the JavaScriptDialogExtensionsClient is saying "hey, yep, that WebContents is really an extension, and there's a special name that you need to use for dialogs spawned by it".

There are two implementations of JavaScriptDialogExtensionsClient::GetExtensionName(). One is the stub implementation in DefaultExtensionsClient, which always returns false. The other is the real implementation used in Chrome, that lives in the extensions code. Let's take a look.

This is implemented in /extensions/components/javascript_dialog_extensions_client/javascript_dialog_extension_client_impl.cc : 

  bool GetExtensionName(content::WebContents* web_contents,
                        const GURL& origin_url,
                        std::string* name_out) override {
    const Extension* extension = GetExtensionForWebContents(web_contents);
    // ...

OK, what does GetExtensionForWebContents() look like?

const Extension* GetExtensionForWebContents(
    content::WebContents* web_contents) {
  return GetProcessManager(web_contents)->GetExtensionForWebContents(
      web_contents);
}

Two calls.

One to GetProcessManager, but that only cares about the BrowserContext/Profile of the WebContents.

One to ProcessManager::GetExtensionForWebContents:

const Extension* ProcessManager::GetExtensionForWebContents(
    const content::WebContents* web_contents) {
  if (!web_contents->GetSiteInstance())
    return nullptr;
  return extension_registry_->enabled_extensions().GetByID(
      GetExtensionIdForSiteInstance(web_contents->GetSiteInstance()));
}

This extracts the SiteInstance for the WebContents, finds the extension id for it, then looks up the extension.

----

What is going on here?

Is this an extensions issue? It's assuming that all WebContentses in the SiteInstance belong to the extension.

If that is a valid assumption: there is a bug in the middle-click logic that allows the new page to spawn in the same SiteInstance/process as the app.

If that is not a valid assumption: there is a bug in the extensions code that assumes that every WebContents in a SiteInstance is an extension WebContents.

Either way this is not a JavaScript dialogs issue.

Remanding to the extensions team for further proceedings consistent with this decision.
Thanks for the analysis, Avi!  Nasko, Charlie, Alex - any insight into whether this is desired behavior or a bug from a process standpoint?  We *could* change the GetExtensionForWebContents() logic to go based on URL, but I'm not sure that's necessarily an improvement.
Components: Blink>WindowDialog

Comment 6 by creis@chromium.org, Jul 19 2017

Cc: lukasza@chromium.org
Comment 3: That's not a valid assumption, so this is a bug in the extensions code.  In this case, we're talking about a hosted app, and hosted app SiteInstances can *definitely* include cross-site web pages that are not part of the hosted app.  (That allows things like OAuth popup dialogs to work.)  We can't assume that the entire SiteInstance is part of the hosted app.

Devlin, can you take a look at updating the extension code here to use the URL?

(As a side note, Ɓukasz changed the behavior of middle click in M60 to open in a new process in  issue 23815 , but this bug could still occur on window.open and targeted links within a hosted app even in M60.)

Comment 7 by a...@chromium.org, Jul 19 2017

Components: -Blink>WindowDialog Platform>Extensions
Cc: -rdevlin....@chromium.org
> Devlin, can you take a look at updating the extension code here to use the URL?

On it.  Will we need to worry about a race condition here?  i.e., the frame is created for a given extension before an url is committed.  (It's possible we might just need to experiment and see).

In cursory exploration, also found crbug.com/746572.  Seems mostly unrelated in terms of the code itself.
Project Member

Comment 9 by sheriffbot@chromium.org, Jul 20 2017

Labels: M-60
Project Member

Comment 10 by sheriffbot@chromium.org, Jul 20 2017

Labels: -Pri-2 Pri-1

Comment 11 by creis@chromium.org, Jul 20 2017

Comment 8: In general, the dialog will be shown by the last committed page, so the last committed URL for the frame is the right thing to use.  You raise a good point about the initial blank document in a frame, though, which could be scripted by the opener/parent.  I guess we'd want to use the origin of the frame in that case, or just fall back to what we do normally do for about:blank (i.e., "This page" for main frames or "An embedded page" for subframes).
Project Member

Comment 12 by sheriffbot@chromium.org, Aug 3 2017

rdevlin.cronin: Uh oh! This issue still open and hasn't been updated in the last 14 days. This is a serious vulnerability, and we want to ensure that there's progress. Could you please leave an update with the current status and any potential blockers?

If you're not the right owner for this issue, could you please remove yourself as soon as possible or help us find the right one?

If the issue is fixed or you can't reproduce it, please close the bug. If you've started working on a fix, please set the status to Started.

Thanks for your time! To disable nags, add the Disable-Nags label.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Thanks for the ping, sheriffbot!

Circling back to this after a week of travel.

@11, my question wasn't just for dialogs, but in general.  We said that ProcessManager::GetExtensionForWebContents() using site instance is incorrect, and should be changed.  One option is to use URL.  But this method is used for a lot more than just JS dialog attribution (task management, dev tools, context menus, and more!).  So even though there's no risk of a race with JS dialogs (because we know that the page must have committed in order to have script running), is that the case for all of them?  Or will we have to worry about a race in certain conditions?  If so, is there any other feasible way to get an extension associated with a given web contents?  (I think we've traditionally used site instance, for better or worse.) 
Project Member

Comment 14 by bugdroid1@chromium.org, Aug 10 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/7a282e33fb1c600499d2c7ff1e633de22865549c

commit 7a282e33fb1c600499d2c7ff1e633de22865549c
Author: Devlin Cronin <rdevlin.cronin@chromium.org>
Date: Thu Aug 10 01:54:10 2017

[Extensions] Account for hosted apps in GetExtensionForWebContents

ProcessManager::GetExtensionForWebContents() returns the extension
associated with a provided web contents. It does this by looking up
the site instance's url, which is handy because it
a) is normalized for extensions and hosted apps (i.e., even hosted
   apps have chrome-extension:// urls in their site instances), and
b) it works before first commit, which is necessary in certain set up
   instances.
   
However, this returns the incorrect result when a vanilla web page is
hosted in a hosted app's site instance. Account for this instance in
the ProcessManager, and add a browser test for the same.

Bug:  746517 
Change-Id: Ibc4a29dd60fb919be9dfe2989f027bc731a4440e
Reviewed-on: https://chromium-review.googlesource.com/604719
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: Charlie Reis <creis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#493219}
[modify] https://crrev.com/7a282e33fb1c600499d2c7ff1e633de22865549c/chrome/browser/extensions/process_manager_browsertest.cc
[modify] https://crrev.com/7a282e33fb1c600499d2c7ff1e633de22865549c/extensions/browser/process_manager.cc
[modify] https://crrev.com/7a282e33fb1c600499d2c7ff1e633de22865549c/extensions/browser/process_manager.h

This should be fixed, and no longer repros for me locally.  anowlcalledjosh@, did you want to verify from your end to double-check?
Yep, looks like this is fixed. Would this be eligible for a reward under the VRP?
Cc: awhalley@chromium.org
Status: Fixed (was: Assigned)
Closing it out.

Adding awhalley@ for VRP.
Labels: reward-topanel
Yep, it will be considered by the panel shortly.  Cheers!
Project Member

Comment 19 by sheriffbot@chromium.org, Aug 12 2017

Labels: -Restrict-View-SecurityTeam Restrict-View-SecurityNotify
Project Member

Comment 20 by sheriffbot@chromium.org, Aug 14 2017

Labels: Merge-Request-61
Project Member

Comment 21 by sheriffbot@chromium.org, Aug 14 2017

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

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
+awhalley@ for M61 merge review.

govind@ - good for 61
Labels: -Merge-Review-61 Merge-Approved-61
Approving merge to M61 branch 3163 based on comment #23. Please merge ASAP. Thank you.
Project Member

Comment 25 by bugdroid1@chromium.org, Aug 14 2017

Labels: -merge-approved-61 merge-merged-3163
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/436901103ce80a654288a39f3ba60e1041d017ec

commit 436901103ce80a654288a39f3ba60e1041d017ec
Author: Devlin Cronin <rdevlin.cronin@chromium.org>
Date: Mon Aug 14 20:40:04 2017

[Extensions] Account for hosted apps in GetExtensionForWebContents

ProcessManager::GetExtensionForWebContents() returns the extension
associated with a provided web contents. It does this by looking up
the site instance's url, which is handy because it
a) is normalized for extensions and hosted apps (i.e., even hosted
   apps have chrome-extension:// urls in their site instances), and
b) it works before first commit, which is necessary in certain set up
   instances.

However, this returns the incorrect result when a vanilla web page is
hosted in a hosted app's site instance. Account for this instance in
the ProcessManager, and add a browser test for the same.

TBR=rdevlin.cronin@chromium.org

(cherry picked from commit 7a282e33fb1c600499d2c7ff1e633de22865549c)

Bug:  746517 
Change-Id: Ibc4a29dd60fb919be9dfe2989f027bc731a4440e
Reviewed-on: https://chromium-review.googlesource.com/604719
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: Charlie Reis <creis@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#493219}
Reviewed-on: https://chromium-review.googlesource.com/614462
Reviewed-by: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/branch-heads/3163@{#553}
Cr-Branched-From: ff259bab28b35d242e10186cd63af7ed404fae0d-refs/heads/master@{#488528}
[modify] https://crrev.com/436901103ce80a654288a39f3ba60e1041d017ec/chrome/browser/extensions/process_manager_browsertest.cc
[modify] https://crrev.com/436901103ce80a654288a39f3ba60e1041d017ec/extensions/browser/process_manager.cc
[modify] https://crrev.com/436901103ce80a654288a39f3ba60e1041d017ec/extensions/browser/process_manager.h

Labels: -Security_Impact-Stable
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.
*********************************
Labels: -Security_Severity-Medium Security_Severity-Low
Nice one! The VRP panel decided to award $500 for this bug. A member of our finance team will be in touch shortly to arrange payment.
Labels: -reward-unpaid reward-inprocess
Project Member

Comment 30 by sheriffbot@chromium.org, Nov 18 2017

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

Sign in to add a comment