W3C home > Mailing lists > Public > public-webappsec@w3.org > April 2019

Re: characterizing framing security needs for webappsec consideration

From: Ian Clelland <iclelland@google.com>
Date: Thu, 18 Apr 2019 10:43:10 -0400
Message-ID: <CAK_TSXLOsXiWWLn4xvXeHcthZe9Jcs8FYF4ArMaytA487admuA@mail.gmail.com>
To: Rouslan Solomakhin <rouslan@google.com>
Cc: Jeff Hodges <jdhodges@google.com>, Web Application Security Working Group <public-webappsec@w3.org>
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

This archive was generated by hypermail 2.3.1 : Thursday, 18 April 2019 14:43:47 UTC