Bug 1591536 [wpt PR 19900] - Prevent sandboxed iframe Document from sharing execution context with initial about:blank Document, a=testonly
authorDaniel Clark <daniec@microsoft.com>
Mon, 04 Nov 2019 11:12:32 +0000
changeset 564760 38ae71a7ccd1e3856ff99053964d9bc95dddcb5d
parent 564759 f083b4e515631d6dc6cd6624fd476ceb560af5cf
child 564761 6f5cc4b1c09a9a21b7f149546eeec6730288dfb7
push id12351
push userffxbld-merge
push dateMon, 02 Dec 2019 11:32:26 +0000
treeherdermozilla-beta@dba4410526a2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1591536, 19900, 1017441, 1881315, 710629
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1591536 [wpt PR 19900] - Prevent sandboxed iframe Document from sharing execution context with initial about:blank Document, a=testonly Automatic update from web-platform-tests Prevent sandboxed iframe Document from sharing execution context with initial about:blank Document This change fixes an issue where a sandboxed iframe can be created such that it contains a sandboxed Document with an opaque origin that still shares a script context with the iframe's initial un-sandboxed about:blank Document. The scenario is set up in the following manner: 1) Create a new iframe dynamically, and set its src to a same-domain page that we are going to sandbox. 2) Insert the iframe into a Document, and synchronously grab a reference to its initial about:blank Document. 3) Synchronously set iframe.sandbox = "allow-scripts" (this is still before the same-domain page has loaded in the frame). 4) The iframe’s navigation to the same-domain page occurs, asynchronously. FrameLoader::ShouldReuseDefaultView is called to determine the mode in which to load the new page. FrameLoader::ShouldReuseDefaultView fails to check the iframe’s sandbox flags (it only looks at the CSP ones), so the navigation proceeds without resetting the type system of the iframe. The result is that the newly loaded page shares the type system of the initial about:blank Document. 5) Code in the sandboxed iframe is now free to make changes to its type system that can affect any usage of the about:blank Document since they share the same type system. This is a sandbox escape in that if the same-domain page that the iframe is navigated to contains user-generated code, it could run outside the iframe. It can also result in crashes if we poke things in the right way, since an object that should be considered cross-origin can bleed into the top-level page, with the result that access checks which are never expected to fail can now fail. This change fixes the issue by making FrameLoader::ShouldReuseDefaultView() check the iframe's sandbox flags via FrameLoader::EffectiveSandboxFlags(), in addition to the existing check for CSP sandbox flags. Bug: 1017441 Change-Id: Ide1b13e16b0e0428a243ff47b6e17ae25ad0ff0d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1881315 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Nate Chapin <japhet@chromium.org> Commit-Queue: Dan Clark <daniec@microsoft.com> Cr-Commit-Position: refs/heads/master@{#710629} -- wpt-commits: 1da988941a8c83f13aa71447a188335f5cc35ab0 wpt-pr: 19900 Differential Revision: https://phabricator.services.mozilla.com/D53550
testing/web-platform/tests/html/browsers/sandboxing/sandbox-new-execution-context-iframe.html
testing/web-platform/tests/html/browsers/sandboxing/sandbox-new-execution-context.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/sandboxing/sandbox-new-execution-context-iframe.html
@@ -0,0 +1,5 @@
+<body>
+  <script>
+    document.__proto__.changeFromSandboxedIframe = "change from sandboxed iframe";
+  </script>
+</body>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/sandboxing/sandbox-new-execution-context.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Reuse of iframe about:blank document execution context</title>
+    <link rel="author" title="Dan Clark" href="mailto:daniec@microsoft.com">
+    <link rel="help" href="http://www.w3.org/html/wg/drafts/html/master/browsers.html#sandboxing">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+
+  <body>
+    <h1>Reuse of iframe about:blank document execution context in sandbox="allow-scripts" iframe</h1>
+    <script type="text/javascript">
+      var t = async_test("iframe with sandbox should load with new execution context")
+
+      let iframe = document.createElement("iframe");
+      iframe.src = './sandbox-new-execution-context-iframe.html';
+      document.body.appendChild(iframe);
+      iframe.sandbox = "allow-scripts";
+
+      let iframeAboutBlankDocument = iframe.contentDocument;
+      assert_equals(iframeAboutBlankDocument.URL, "about:blank");
+
+      iframe.onload = t.step_func_done(() => {
+        assert_equals(iframe.contentDocument, null,
+          "New document in sandboxed iframe should have opaque origin");
+
+        assert_equals(iframeAboutBlankDocument.__proto__.changeFromSandboxedIframe, undefined,
+          "Sandboxed iframe contents should not have been able to mess with type system of about:blank document");
+
+        let iframeAboutBlankContents = iframeAboutBlankDocument.querySelectorAll('body');
+        assert_equals(iframeAboutBlankContents[0].tagName, "BODY",
+          "about:blank document's contents should still be accessible");
+
+        t.done();
+      });
+    </script>
+    <div id="log"></div>
+  </body>
+</html>