Open Bug 1614408 Opened 4 years ago Updated 4 years ago

"Cross-origin" properties available on CSP-blocked iframe until load is complete

Categories

(Core :: DOM: Security, defect, P3)

defect

Tracking

()

People

(Reporter: jgraham, Unassigned)

References

Details

(Whiteboard: [domsecurity-backlog1])

Attachments

(1 file)

Attached patch patchSplinter Review

The basic scenario is that a script creates an iframe and sets the src to a document that should be blocked by a CSP directive (in this case frame-ancestors). Once the document load is complete, properties on the iframe like contentWindow.location.href are blocked as cross-origin. But up until the point that the load completes those properties remain accessible, both for the initial about:blank document (expected) and the actual document that would be loaded (less expected).

I suspect this isn't a security issue because I expect that all information that can be accessed is already available to the script at the point it creates the iframe. But I'm not sure. And it's at least surprising to see the properties change from accessible to inaccessible as the load progresses.

The testcase I have requires applying the attached patch either to a web-platform-tests checkout, or to mozilla-central with --dir testing/web-platform/tests. Then run a test in content-security-policy/frame-ancestors/ e.g. with ./mach wpt /content-security-policy/frame-ancestors/frame-ancestors-nested-same-in-cross-url-block.html The console will show the result of attempting to access the ev.target.contentWindow.location.href property for each poll attempt which, depending on timing, is typically about:blank followed by the URL of the iframe, followed by an exception.

The basic scenario is that a script creates an iframe and sets the src to a document that should be blocked by a CSP directive

That src starts out same-origin, right? And the CSP comes from an HTTP header, not <meta>?

What I would expect happens here is:

  1. Subframe created with about:blank URL, which is same-origin with parent.
  2. Response is received from the server, is same-origin with parent.
  3. We examine the CSP in the HTTP header, do those CSP checks, and replace the page with an error page or whatever is supposed to happen when frame-ancestors checks fail; this part is not specced very clearly. The error page is not-same-origin, so you get the .href get failures.

But it sounds like instead of step 3 we create the new document based on the response, then (maybe sync?) do the CSP check, then, async, load the error page? So there are three states here: about:blank, response document, error page, and the polling is seeing all of them.

What does the spec say about the order in which document creation and CSP frame-ancestors enforcement are supposed to happen?

Flags: needinfo?(ckerschb)

To answer the spec question, https://html.spec.whatwg.org/#process-a-navigate-response does the "Should navigation response to navigation request of type from source in target be blocked by Content Security Policy?" check, which should land in https://w3c.github.io/webappsec-csp/#should-block-navigation-response and do CSP checks. This happens before a Document is created.

In our impl, there's the PermitsAncestry call in Document::StartDocumentLoad, which is way too late.

With fission enabled, we do the check earlier, and in the parent process. There are comments there about workarounds for bug 1574372, but that bug is fixed.

In any case, even if we are doing this stuff in the child process, we could ParseCSPAndEnforceFrameAncestorCheck without doing the whole "wait until StartDocumentLoadthing, right? In particular, do it innsDSURIContentListener::DoContentor anywhere between there and the document creation innsContentDLF::CreateDocument`.

Do we think the issue here is serious enough I should hold back on making a patch to fix the test timeouts (that's basically the attached patch)?

Let me leave a few notes which might add value to the problems discussed here:

  • We just fixed a very similar issue for x-frame-options; in the iframe-gets-blocked case the content within the iframe was available for some period of time till it was replaced by the actual error page. As a workaround we decided to basically sandbox the load by using a NullPrincipal till the error page is loaded (see https://phabricator.services.mozilla.com/D61862). Obviously that's not a perfect solution but at least does the trick as an interim fix.

  • I am actively working on Bug 1599131 which will move CSP frame-ancestors and also x-frame-options checks into the parent, not only for fission mode, but also for regular mode. So checks will happen way before any content is loaded, so the entire problem should disappear within this cycle.

Flags: needinfo?(ckerschb)

I think fixing the test timeouts here should be fine, personally.

Group: core-security → dom-core-security

I don't believe there's an actual security bug here -- all the "leaked" info is known already.

Group: dom-core-security

Hey James, it seems Boris is fine with fixing the tests here (see comment 6) - do you wanna upload your patch and r? someone? I could greenlight it if needed - thanks!

Flags: needinfo?(james)

I fixed the most egregious failures in bug 1614674; there are still some CSP tests that time out which I need to investigate but they're more spread out.

Flags: needinfo?(james)
See Also: → 1614674

The priority flag is not set for this bug.
:ckerschb, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(ckerschb)

In that case I'll make it dependent on Bug 1599131 which I am working on - once fixed we can re-evaluate what we do with this bug. Putting in the backlog for now.

Depends on: 1599131
Flags: needinfo?(ckerschb)
Priority: -- → P3
Whiteboard: [domsecurity-backlog1]
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: