- From: Ian Clelland <iclelland@google.com>
- Date: Thu, 18 Apr 2019 10:43:10 -0400
- To: Rouslan Solomakhin <rouslan@google.com>
- Cc: Jeff Hodges <jdhodges@google.com>, Web Application Security Working Group <public-webappsec@w3.org>
- Message-ID: <CAK_TSXLOsXiWWLn4xvXeHcthZe9Jcs8FYF4ArMaytA487admuA@mail.gmail.com>
That's definitely not an attack scenario we'd considered (or that I've considered) extensively. What you're suggesting is that a site may want to use a feature when at the top level, but wants to have itself restricted when it is embedded. X-Frame-Options can certainly be used to prevent embedding all together, and https://good-site.com has other options to detect this and protect itself if it is important -- checking window.parent === window to know that it has been framed is one way; I'm sure there are others. On Wed, Apr 17, 2019 at 10:01 AM Rouslan Solomakhin <rouslan@google.com> wrote: > > > On Wed, Apr 17, 2019 at 1:08 AM Ian Clelland <iclelland@google.com> wrote: > >> Hi Jeff, >> >> PaymentRequest was actually one of the very first features to utilize >> Feature Policy in Chrome -- by design, it should be able to handle allowing >> and restricting that API in same- and cross-origin embedding scenarios. >> I've added more detailed comments inline, but the shortest answer is that >> this *should* all work the way Rouslan has described, and that yes, we may >> need to add something to the spec if we want to *require* an opt-in from >> the embedded page. >> >> On Tue, Apr 16, 2019 at 8:56 PM Jeff Hodges <jdhodges@google.com> wrote: >> >>> HI WebAppSec folk, >>> >>> I've been corresponding with Rouslan over in the Web Payments working >>> group regarding Feature Policy in cross-origin iFrames and sandboxed >>> iFrames and how they might be used for a couple of use cases he/they have. >>> It would seem to have relevance for the still-to-be addressed question of >>> policies wrt WebAuthn in cross-origin iFrames. >>> >>> This is kinda long, but this stuff is complex. I'll try adding it to the >>> end of the agenda for tomorrow's call... >>> >>> On Tue, Apr 16, 2019 at 6:52 AM Rouslan Solomakhin <rouslan@google.com> >>> wrote: >>> >>>> Thank you for the reply, Jeff! Please see my comments inline. >>>> >>>> On Mon, Apr 15, 2019 at 9:46 PM Jeff Hodges <jdhodges@google.com> >>>> wrote: >>>> >>>>> >>>>> On Wed, Apr 3, 2019 at 5:31 PM Rouslan Solomakhin <rouslan@google.com> >>>>> wrote: >>>>> >>>>>> Here's a summary of the needs/considerations for the Web Payment APIs: >>>>>> >>>>>> *#1: Would it be possible to disable certain powerful APIs (e.g., >>>>>> Payment Request and Payment Handler) in embedded cross-origin iframes by >>>>>> default, unless the embedded iframe explicitly allows to be embedded for >>>>>> the purpose of payments?* Concretely, this could be something like a <meta >>>>>> allow-when-embedded="payments"> tag, for example. >>>>>> >>>>> >>>>> *In my reading of Feature Policy >>>>> <https://w3c.github.io/webappsec-feature-policy/>, it seems this use case >>>>> is addressed*. For embedding origin example-embedding.foo, and >>>>> embedded origin example-embedded.bar, the embedding webapp would >>>>> declare on the embedded iframe: >>>>> >>>>> `<iframe allow="payment example-embedded.bar" ...>` >>>>> >>>>> and example-embedded.bar would return a "header policy" (from which >>>>> the UA forms the embedded content's "declared policy"), like so: >>>>> >>>>> `Feature-Policy: payment 'self';` >>>>> >>>>> And then the magic Feature Policy algorithm Is feature enabled in >>>>> document for origin >>>>> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled> >>>>> combines the two policy declarations and comes up with "Enabled" for >>>>> the "payment" feature in the cross-origin iframe. >>>>> >>>> >>>> Is my understanding correct that example-embedded.bar does not have to >>>> specify a "header policy" for payments to work? >>>> >>> >>> I *think* the answer is "no" because this use case is explicitly >>> cross-origin (however, see below). I think the answer is "yes" if it were >>> a same-origin use case. >>> >> >> As currently specced, Feature Policy does *not* require >> example-embedded.bar to declare a policy through HTTP headers in order to >> use PaymentRequest. If PaymentRequest is allowed in the embedding document >> by its own feature policy, and it uses an iframe tag like the one above, >> then it will also be allowed in the embedded document. >> >> By the spec, when the embedded document is created, we will define an >> inherited policy for it, using the embedding document's policy and the >> container policy constructed from the iframe element. In this case, the >> inherited policy for the "payment" feature will be Enabled. Without a >> Feature-Policy header, the embedded document's policy will not have a >> declared policy for the "payment" feature. >> >> With that policy in place, when the embedded document tries to use >> PaymentRequest, it should call Is feature enabled in document for origin >> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled> >> with its own document and its own origin as arguments. Because the >> inherited policy is "Enabled", and the feature is *not* present in the >> declared policy, that algorithm will fall through to step 5, discover that >> "origin" is same origin-domain with document's origin (the origins should >> be identical because of how it was called), and return True. >> >> >> >>> So, upon further grovelling thru the Feature Policy spec, I am unsure >>> whether it can be employed to allow cross-origin feature use. The spec >>> seems unclear whether the Should request be allowed to use feature >>> <https://w3c.github.io/webappsec-feature-policy/#algo-should-request-be-allowed-to-use-feature> alg >>> is invoked in the case where JS running in the embedded frame invokes >>> PaymentRequest ? >>> >> >> I'm not sure which spec you mean when you say that it is unclear -- I'll >> explain the specs as I understand the relationship, but I'd be happy to >> make changes where I can to make it clearer: >> >> The Payment Request API spec says that the PaymentRequest constructor >> <https://www.w3.org/TR/payment-request/#constructor> should call HTML's >> "allowed to use" algorithm with the current document. That algorithm >> <https://html.spec.whatwg.org/multipage/iframe-embed-object.html#allowed-to-use> is >> what calls Is feature enabled in document for origin >> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled>, >> and it always calls it with the document and the document's own origin, so >> the same-origin check should always be true (when called from HTML). >> >> >>> The Is feature enabled in document for origin >>> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled> >>> alg, which does the combining of inherited, declared, and default policies, >>> appears to only be called from the former alg. >>> >> >> It's also called from Define an inherited policy for feature in >> container at origin >> <https://w3c.github.io/webappsec-feature-policy/#define-an-inherited-policy-for-feature-in-container-at-origin>, >> but more importantly, it's called from HTML: it's an exported algorithm >> that can be used as an entry point into Feature Policy from other specs. >> >> >>> Also, if the *document* that is passed to the latter alg is the >>> top-level document, then the embedded document's declared policy (if any) >>> is not evaluated by the latter alg. And so this scenario would not work. :( >>> >> >> Generally, the document passed to Is feature enabled in document for >> origin >> <https://w3c.github.io/webappsec-feature-policy/#algo-is-feature-enabled>, when >> used to answer "can a document use this feature?", is the document which is >> trying to use the feature, not the top-level doc. >> >> >>> If this is correct, then I am proposing that we make an exception for >>>> "payment" specifically to always require the "header policy" in the >>>> embedded iframe. This would be a change in the spec and, therefore, >>>> implementations, if I understand correctly. >>>> >>> >> We have discussed the idea that some features need an explicit opt-in >> from the embedded site in order to be *disabled* -- this turns out to be >> important when disabling existing functionality; I don't know if anyone has >> considered requiring the same opt-in for *enabling* a feature. My belief >> has always been that if the embedding document is trusted to use the >> feature, then it should be able to delegate that to the documents that it >> embeds (if it trusts them as well). Are you suggesting that use of >> PaymentRequest should also require such an opt-in from the *embedded >> document*? >> > > Yep, that's what I am suggesting. Any HTTPS top-level context can use > PaymentRequest and PaymentHandler today, including https://evil.com. If > https://evil.com has an <iframe allow="payment" src="https://good-site.com"></iframe>, > then https://good-site.com will call PaymentRequest and be none the wiser > that it's not in complete control of what HTML content the user is looking > at. Do you think that Feature Policy is the right tool to solve this > problem? > > >> In any case, regardless whether Feature Policy is actually intended to >>> support the above feeble cross-origin example (this is not made clear in >>> the spec, ISTM), I am now guessing that the above example "header policy" >>> (i.e., Feature-Policy header field) ought to perhaps be: >>> >>> `Feature-Policy: payment example-embedding.foo;` >>> >>> ..and am wondering whether that would be a reasonable way for the >>> combination of the embedding and embedded parties to explicitly declare >>> that such cross-origin use of a feature(s) is allowed? (this must have >>> already been discussed ?) >>> >>> >>> >>> >>>> #2: Would it be possible to disable these powerful APIs in all iframes >>>>>> that are not sandboxed? Cross origin iframes today have to look like this: >>>>>> <iframe allow="payments" src="https://payment-app.com/some.js"></iframe>, >>>>>> if the parent iframe wants to allow payments in the child iframe. Would it >>>>>> be kosher to require the tag to look like this: <iframe *sandbox* >>>>>> allow="payments" src="https://payment-app.com/some.js" ></iframe> ? >>>>>> >>>>> >>>>> Sandbox attribute is defined here >>>>> <https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox> >>>>> . >>>>> >>>>> Given that definition, it seems that the sandbox attr does not match >>>>> your above use case. The sandbox attr is about protecting the embedding >>>>> webapp from the framed webapp/content (and not vice-versa), and also not >>>>> about controlling whether powerful features are enabled or not (the latter >>>>> is the province of Feature Policy). >>>>> >>>>> That said however, it may be overall reasonable standard best practice >>>>> for embedders to declare many iframes (in general) like so: >>>>> >>>>> <iframe sandbox="allow-same-origin allow-forms allow-scripts" src=" >>>>> https://maps.example.com/embedded.html"></iframe> >>>>> >>>>> ..because it disables plugins and popups, thus reducing the risk of >>>>> the user being exposed to malware and other annoyances. >>>>> >>>> >>>> It feels like a payment sheet can fall into the category of "other >>>> annoyances." >>>> >>> >>> Possibly? >>> >>> >>>> I am proposing to change the spec to say: "if the cross-origin iframe >>>> does not have a sandbox attribute, then disable the payment APIs in that >>>> iframe." Does that sound reasonable? >>>> >>> >>> By spec, you're referring to the Payment Request spec? >>> >>> I remain uncertain that requiring the sandbox attr is appropriate. >>> >>> >>> However, the framed webapp is able to escape the sandbox relatively >>>>> easily. See examples and warnings in Sandbox attribute definition >>>>> <https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox> >>>>> . >>>>> >>>> >>>> Is my reading of the spec correct that only iframes from the same >>>> origin as the embedder can escape sandbox? >>>> >>> >>> That seems to be implied? >>> >>> HTH, >>> >>> =JeffH >>> >>> >>> >>
Received on Thursday, 18 April 2019 14:43:46 UTC