w3c / secure-payment-confirmation

Secure Payment Confirmation (SPC)
https://w3c.github.io/secure-payment-confirmation/
Other
110 stars 39 forks source link

Clarification on requiring user activation for credential creation in cross-origin iframes to mitigation cross-site tracking #128

Closed caraitto closed 2 years ago

caraitto commented 3 years ago

https://github.com/w3c/secure-payment-confirmation/blob/main/explainer.md#enrollment-in-cross-origin-iframes mentions that "if site A embeds an iframe from site B, with the "payment" policy set, then site B may initiate a credential creation for site B within that iframe", with a proposed mitigation of requiring transient user activation.

For secure payment confirmation specifically, would the credential creation only happen after the browser payment UX flow is completed by the user? The browser payment UX seems stronger than mere user activation, since it's controlled by the browser and can't be faked (for instance, a page couldn't "for example - overlay a transparent iframe on-top of a legitimate button" on top of the payment UX for the purpose of cross-site tracking). Is there something I'm missing?

rsolomakhin commented 2 years ago

would the credential creation only happen after the browser payment UX flow is completed by the user

The browser payment UX flow is not involved in registering a new credential. As it stands right now, registering a credential can be done without any browser UX, just like in WebAuthn.

The browser payment UX flow is used when the website is "getting an assertion", i.e., asking for a signature over payment data, using an already existing credential. That's when the browser shows its own payment UX flow.

The browser payment UX ... can't be faked

A webpage can make a fake browser payment UX that 90% of users will not notice is fake.

The security of SPC comes more from the fact that the webpage is unable to modify the "clientDataJSON" values that the authenticator signs cryptographically. If the webpage calls navigator.credentials.get() for some public key credential, then "clientDataJSON.type" will be "webauthn.get", whereas SPC API call will return a "clientDataJSON.type" of "payment.get", among other differences.

a page couldn't "for example - overlay a transparent iframe on-top of a legitimate button" on top of the payment UX

That is correct.

caraitto commented 2 years ago

The security of SPC comes more from the fact that the webpage is unable to modify the "clientDataJSON" values that the authenticator signs cryptographically. If the webpage calls navigator.credentials.get() for some public key credential, then "clientDataJSON.type" will be "webauthn.get", whereas SPC API call will return a "clientDataJSON.type" of "payment.get", among other differences.

My threat concern isn't so much about security, as cross-site identifiability -- I'm trying to determine if this API could be used to build an identifier that can be read by multiple (possibly colluding) origins such that this identifier could be used as a "joining key", linking identities from one site to another.

would the credential creation only happen after the browser payment UX flow is completed by the user

The browser payment UX flow is not involved in registering a new credential. As it stands right now, registering a credential can be done without any browser UX, just like in WebAuthn.

Since it sounds like this credential can be created in a third-party iframe -- can this credential be read by the page (somehow sent to the page's server) after creation? If so, in these 2 scenarios:

1: top: foo.com iframe: bar.com

2: top: baz.com iframe: bar.com

...does bar.com get to read the same credential in both cases? If so, it sounds like a cross-site tracking vector? Requiring user activation to create the credential helps some, but sometimes the page can coax the user with misleading UX to harvest gestures. The issue still exists if the user makes a payment, but at least they're placing some implicit trust in the site by making a payment.

If it's not possible for bar.com to read the credential until the payment completes (i.e., it's read-only stored in the browser until the payment is approved by the user), this would mitigate the concern.

The browser payment UX ... can't be faked

A webpage can make a fake browser payment UX that 90% of users will not notice is fake.

Correct -- the thought was that if the real payment UI was required to create the credential, a fake payment UI implemented in HTML/CSS/JS wouldn't be able to create the credential, even if the user was tricked into believing that the UI is the real browser UI and not a fake.

But, credential creation without requiring the payment UI should be OK, as long as reading the credential requires the payment UI flow to complete.

stephenmcgruer commented 2 years ago

I think that there's some confusion in this issue over registration (a one-time process that does not necessarily involve a payment, and which results in a created WebAuthn credential) and authentication (a many-time process that does involve a payment, and which utilizes an already-created WebAuthn credential). It may be worth reading the SPC introduction section if not already done so.

In terms of the foo.com, baz.com, bar.com example: if a credential already exists for bar.com (the child), then being able to read such a credential in a 3p iframe is possible in WebAuthn today: one can call navigator.credential.get() in an iframe, without user activation, if the parent frame has given the iframe the publickey-credentials-get policy (https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy).

SPC inherits this behavior, so nothing is new on that side. (In fact, as noted, we throw up a bunch of payments UX that probably makes the read even worse, and we require a user activation).

But, credential creation without requiring the payment UI should be OK, as long as reading the credential requires the payment UI flow to complete.

Confirming the credentials existence does require the user to agree to the payment UX (and then complete the subsequent WebAuthn UX and interaction too). Again, note that WebAuthn today allows read in a 3p iframe without SPC's UX or requirement for user activation.

What is relevant to think about here is the registration part. SPC allows a site to create a credential in a 3p iframe, whereas in WebAuthn the user would have to be redirected to or otherwise visit the page (bar.com in the above example). This is discussed in the explainer as noted in the OP, and also in a bit more detail in the spec: https://w3c.github.io/secure-payment-confirmation/#sctn-security-cross-origin-registration

This is definitely a feasible privacy attack, albeit we note it requires either cooperation from the main frame (in which case one is somewhat out of luck anyway) or script injection into the main frame. There is a little bit of defense in the WebAuthn creation UX that will be shown, which would identify to the user that the credential is for bar.com not foo.com, but we acknowledge that users don't usually read such UX in enough detail anyway.

caraitto commented 2 years ago

Thanks for some additional background -- I'm still investigating the existing WebAuthn tracking potential.

Just wanted to clarify:

requires either cooperation from the main frame (in which case one is somewhat out of luck anyway)

Our threat model assumes that the main frame and subframe can collude.

Maybe it would be good to schedule a meeting? I'll reach out internally.

stephenmcgruer commented 2 years ago

@caraitto, @rsolomakhin , and I met yesterday to discuss this issue. The main outcomes were that (and please correct me if I'm wrong here, @caraitto ):

  1. There is a concern that the creation of a WebAuthn credential in a cross-origin iframe could make it easier for a malicious actor to create a tracking vector in the form of a WebAuthn credential.
  2. However the existence of the WebAuthn UI for both creation and use (as well as the payments UI for use via SPC) seems a sufficient roadblock to avoid this being widely/successfully exploited.
  3. We (the Working Group) should consider additionally adding a user activation requirement for credential creation in a cross-origin iframe, as an additional layer of defence for users (e.g. they would have to interact with an iframe before it could attempt credential creation).

Let's discuss the user-activation suggestion at the next task force meeting.

caraitto commented 2 years ago

Thanks @stephenmcgruer -- this sounds like a good summary. I think it would be good to consider adding an activation requirement.

stephenmcgruer commented 2 years ago

To give a direction for the upcoming TPAC discussion on this issue: I propose that we adopt requiring a user activation for creation of an SPC credential.

ianbjacobs commented 2 years ago

Tracking related discussion in WebAuthn https://github.com/w3c/webauthn/issues/1293

stephenmcgruer commented 2 years ago

Coming back to this issue (which was not discussed at TPAC). I think for user protection, we should require user-activation for credential creation when the payment extension is specified (e.g., for SPC-enabled credentials). To this end, I have created a draft PR that would enforce this - https://github.com/w3c/secure-payment-confirmation/pull/178

There are two main considerations here when thinking about landing this (beyond the security/privacy improvement):

  1. This would be a breaking change, as the current implementation does not require user-activation.
  2. WebAuthn itself does not require user-activation for either registration or authentication, though it is under discussion.

For (1), I believe that all known users of SPC currently have a user-activation anyway in their registration flows, though we should check that.

For (2), I believe that this extra step is necessary here because we allow registration in a cross-origin iframe, which is more dangerous than WebAuthn's case. Also, requiring it is more stringent than not, so if in the future we wanted to 'walk it back' and change our minds, it would be backwards compatible to do so.

ianbjacobs commented 2 years ago

@jcemer-stripe, @ACathelin, could you confirm that your flows include user activation? Thanks!

jcemer-stripe commented 2 years ago

Yes, our current flow includes user activation. We aren't prompting enrollment before user acknowledging it.

ianbjacobs commented 2 years ago

Adding @Eric-Alvarez to see if we can hear Adyen perspective.

stephenmcgruer commented 2 years ago

@caraitto - we've now merged a PR to add a user-activation requirement for credential creation in a cross-origin iframe (see #178 ), and plan to ship the change in M103 (https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/GSoWLFb_jF0). Can you confirm that this issue is resolved to your satisfaction?

caraitto commented 2 years ago

Thanks, LGTM.

Your new blink-dev I2S will get picked up by the next reviewer in our rotation, which it looks like won't be me, but they should see the activation requirement introduced by your PR.

stephenmcgruer commented 2 years ago

Thanks caraitto, closing this issue then as the spec change has landed :).