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

Issue 756712 link

Starred by 2 users

Issue metadata

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



Sign in to add a comment

Security: Credentials API does not require call to navigator.credentials.store to share credentials across subdomain

Reported by lawn...@gmail.com, Aug 18 2017

Issue description

VULNERABILITY DETAILS
The Credentials API exposes credentials that were saved by the user on subdomain A.foo.com to subdomain B.foo.com without subdomain A.foo.com calling navigator.credentials.store().

Based on the blog post[1] in June announcing this feature, which said:

> You must explicitly store the password using navigator.credentials.store(), so that when a user chooses a credential by tapping on the dialog, the password gets passed and copied to the current origin.

...the reproduction case below demonstrates a bug.

However, AFAICT, the spec[2] allows this behavior.

I'll first say that we opened this as a security bug out of an abundance of caution. We understand that the reproduction likely demonstrates intended behavior. That being said, we believe that behavior to be surprising and dangerous. Frankly, it really seems like this breaks the web.

Specifically, in our opinion, the user indicating that they want to save credentials on a subdomain should *not* be a signal to their user agent that any other subdomain can ask them for those credentials in plaintext (or any other form) without the original subdomain's explicit consent.

1: https://developers.google.com/web/updates/2017/06/credential-management-updates#credentials_can_be_shared_from_a_different_subdomain
2: https://w3c.github.io/webappsec-credential-management/#security-credential-access
3: https://developers.google.com/web/updates/2017/03/nic57

VERSION
Chrome Version: 57+ stable
Operating System: All (Tested on MacOS only)

REPRODUCTION CASE
1) Navigate to https://admin-dot-example.glitch.me/
2) Enter a username and password and click 'Log in'
3) Click 'Save' to indicate you want Google Smart Lock to save your password for this site
4) Click 'Click here to repro' link
5) Click 'Sign In' to indicate you want to sign in with your account saved with Google Smart Lock
6) Observe that your username and password are displayed
 
Components: Blink>SecurityFeature>CredentialManagement
Status: Untriaged (was: Unconfirmed)
Yes, I expect https://developers.google.com/web/updates/2017/06/credential-management-updates#credentials_can_be_shared_from_a_different_subdomain is simply misleading, in that it omits the possibility that the password was saved by the user rather than navigator.credentials.store().


Comment 2 by lawn...@gmail.com, Aug 18 2017

I should note that we are aware that Chrome has implemented password autofill across subdomains for some time. So, for example, these steps result in the same disclosure of credentials:

1) Navigate to https://admin-dot-example.glitch.me/
2) Enter a username and password and click 'Log in'
3) Click 'Save' to indicate you want Google Smart Lock to save your password for this site
4) Navigate to https://www2-dot-example.glitch.me/
5) Click in the Username form field and select the username you entered in step 2
6) Observe that your username and password are displayed

However, in this case, attackers have to construct a login form that appears legitimate to the user. In many cases, the attacker's login form must be customized for each target subdomain. The Smart Lock dialog, however, appears the same regardless of which subdomain asks the browser to display it. We feel this makes the attacker's job substantially easier. For example, a malicious ad could try to sniff credentials whenever it is displayed outside an iframe.

We're happy to file this issue with the spec instead, if y'all decide that it's working as expected. Thanks!

Comment 3 by lawn...@gmail.com, Aug 23 2017

We have identified a potential workaround that *may* satisfy our needs: we can use Object.defineProperty to clobber navigator.credentials on pages where we don't want navigator.credentials.get to be called:

```
Object.defineProperty(navigator, 'credentials', {
  configurable: false,
  enumberable: true,
  value: {
    get: () => Promise.reject('Credentials API disabled')
  },
  writable: false
});
```

The below steps demonstrate that the original reproduction steps no longer disclose credentials:
1) Navigate to https://admin-dot-example.glitch.me/
2) Enter a username and password and click 'Log in'
3) Click 'Save' to indicate you want Google Smart Lock to save your password for this site
4) Navigate to https://www3-dot-example.glitch.me/
5) Observe that 'Exploit failed: Credentials API disabled' is displayed

This sort of thing always makes me nervous - there can be many ways to reach and use a particular value in JS. Thus far, I've not found any way to use the original values in question that doesn't throw an 'Illegal invocation' or a DOMException. I suspect I've not tried everything.

Note that this workaround may not work in browsers with different ideas about how Object.defineProperty interacts with host objects.

Comment 4 by ta...@google.com, Aug 25 2017

Cc: mkwst@chromium.org battre@chromium.org
Labels: Security_Severity-Medium Security_Impact-Stable OS-All
Owner: vasi...@chromium.org
Status: Assigned (was: Untriaged)
vasilii@, would you be the right person to resolve this?
Project Member

Comment 5 by sheriffbot@chromium.org, Aug 26 2017

Labels: M-61
Project Member

Comment 6 by sheriffbot@chromium.org, Aug 26 2017

Labels: Pri-1
Status: WontFix (was: Assigned)
That was a conscious decision. A credential for a subdomain is offered in the account chooser. It always requires a user click before it's returned. You may see the (i) icon next in the dialog which displays the origin on hover. Without the feature UX suffers a lot. Imagine a credential saved for facebook.com and later used on m.facebook.com.

If you want to suppress it then the right way would be to add your site to the public suffix list (https://publicsuffix.org/). Note, that without that step the two sites share cookies with each other. It's not secure too.

Comment 8 by lawn...@gmail.com, Aug 28 2017

Ok. I'll file a bug with the spec. Thanks for taking a look.
Project Member

Comment 10 by sheriffbot@chromium.org, Dec 4 2017

Labels: -Restrict-View-SecurityTeam 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