Title: [231730] trunk
Revision
231730
Author
[email protected]
Date
2018-05-11 21:11:16 -0700 (Fri, 11 May 2018)

Log Message

X-Frame-Options: SAMEORIGIN needs to check all ancestor frames
https://bugs.webkit.org/show_bug.cgi?id=185567
<rdar://problem/40175008>

Reviewed by Brent Fulgham.

Source/WebCore:

Change the behavior of "X-Frame-Options: SAMEORIGIN" to ensure that all ancestors frames
are same-origin with the document that delivered this header. This prevents an intermediary
malicious frame from clickjacking a child frame whose document is same-origin with the top-
level frame. It also makes the behavior of X-Frame-Options in WebKit more closely match
the behavior of X-Frame-Options in other browsers, including Chrome and Firefox.
        
Currently a document delivered with "X-Frame-Options: SAMEORIGIN" must only be same-origin
with the top-level frame's document in order to be displayed. This prevents clickjacking by
a malicious page that embeds a page delivered with "X-Frame-Options: SAMEORIGIN". However,
it does not protect against clickjacking of the "X-Frame-Options: SAMEORIGIN" page (victim)
if embedded by an intermediate malicious iframe, say a "rogue ad", that was embedded in a
document same origin with the victim page. We should protect against such attacks. 

Tests: http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html
       http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::shouldInterruptLoadForXFrameOptions):

Source/WebKit:

Change the behavior of "X-Frame-Options: SAMEORIGIN" to ensure that all ancestors frames
are same-origin with the document that delivered this header. This prevents an intermediary
malicious frame from clickjacking a child frame whose document is same-origin with the top-
level frame. It also makes the behavior of X-Frame-Options in WebKit more closely match
the behavior of X-Frame-Options in other browsers, including Chrome and Firefox.
        
Currently a document delivered with "X-Frame-Options: SAMEORIGIN" must only be same-origin
with the top-level frame's document in order to be displayed. This prevents clickjacking by
a malicious page that embeds a page delivered with "X-Frame-Options: SAMEORIGIN". However,
it does not protect against clickjacking of the "X-Frame-Options: SAMEORIGIN" page (victim)
if embedded by an intermediate malicious iframe, say a "rogue ad", that was embedded in a
document same origin with the victim page. We should protect against such attacks.

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::shouldInterruptLoadForXFrameOptions):

LayoutTests:

Add tests to ensure that "X-Frame-Options: SAMEORIGIN" checks ancestor frames.

* http/tests/cookies/same-site/fetch-after-navigating-iframe-in-cross-origin-page.html:
* http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html:
* http/tests/cookies/same-site/fetch-in-cross-origin-iframe.html:
* http/tests/resources/echo-iframe-src.php: Copied from LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php.
* http/tests/security/XFrameOptions/resources/x-frame-options-ancestors-same-origin-deny.html: Added.
* http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi: Added.
* http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi: Added.
* http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow-expected.txt: Added.
* http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html: Added.
* http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny-expected.txt: Added.
* http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html: Renamed from LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (231729 => 231730)


--- trunk/LayoutTests/ChangeLog	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/LayoutTests/ChangeLog	2018-05-12 04:11:16 UTC (rev 231730)
@@ -1,3 +1,25 @@
+2018-05-11  Daniel Bates  <[email protected]>
+
+        X-Frame-Options: SAMEORIGIN needs to check all ancestor frames
+        https://bugs.webkit.org/show_bug.cgi?id=185567
+        <rdar://problem/40175008>
+
+        Reviewed by Brent Fulgham.
+
+        Add tests to ensure that "X-Frame-Options: SAMEORIGIN" checks ancestor frames.
+
+        * http/tests/cookies/same-site/fetch-after-navigating-iframe-in-cross-origin-page.html:
+        * http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html:
+        * http/tests/cookies/same-site/fetch-in-cross-origin-iframe.html:
+        * http/tests/resources/echo-iframe-src.php: Copied from LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php.
+        * http/tests/security/XFrameOptions/resources/x-frame-options-ancestors-same-origin-deny.html: Added.
+        * http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi: Added.
+        * http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi: Added.
+        * http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow-expected.txt: Added.
+        * http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html: Added.
+        * http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny-expected.txt: Added.
+        * http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html: Renamed from LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php.
+
 2018-05-11  Nan Wang  <[email protected]>
 
         AX: In role=dialog elements with aria-modal=true VoiceOver iOS/macOS can't manually focus or read dialog paragraph description text inside the modal.

Modified: trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-navigating-iframe-in-cross-origin-page.html (231729 => 231730)


--- trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-navigating-iframe-in-cross-origin-page.html	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-navigating-iframe-in-cross-origin-page.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -11,7 +11,7 @@
     await setCookie("implicit-strict", "6", {"SameSite": null, "Max-Age": 100, "path": "/"});
     await setCookie("strict-because-invalid-SameSite-value", "6", {"SameSite": "invalid", "Max-Age": 100, "path": "/"});
     await setCookie("lax", "6", {"SameSite": "Lax", "Max-Age": 100, "path": "/"});
-    window.location.href = ""
+    window.location.href = ""
 }
 runTest();
 </script>

Modified: trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html (231729 => 231730)


--- trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/LayoutTests/http/tests/cookies/same-site/fetch-after-top-level-navigation-initiated-from-iframe-in-cross-origin-page.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -11,7 +11,7 @@
     await setCookie("implicit-strict", "4", {"SameSite": null, "Max-Age": 100, "path": "/"});
     await setCookie("strict-because-invalid-SameSite-value", "4", {"SameSite": "invalid", "Max-Age": 100, "path": "/"});
     await setCookie("lax", "4", {"SameSite": "Lax", "Max-Age": 100, "path": "/"});
-    window.location.href = ""
+    window.location.href = ""
 }
 runTest();
 </script>

Modified: trunk/LayoutTests/http/tests/cookies/same-site/fetch-in-cross-origin-iframe.html (231729 => 231730)


--- trunk/LayoutTests/http/tests/cookies/same-site/fetch-in-cross-origin-iframe.html	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/LayoutTests/http/tests/cookies/same-site/fetch-in-cross-origin-iframe.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -11,7 +11,7 @@
     await setCookie("implicit-strict", "3", {"SameSite": null, "Max-Age": 100, "path": "/"});
     await setCookie("strict-because-invalid-SameSite-value", "3", {"SameSite": "invalid", "Max-Age": 100, "path": "/"});
     await setCookie("lax", "3", {"SameSite": "Lax", "Max-Age": 100, "path": "/"});
-    window.location.href = ""
+    window.location.href = ""
 }
 runTest();
 </script>

Deleted: trunk/LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php (231729 => 231730)


--- trunk/LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/LayoutTests/http/tests/cookies/same-site/resources/echo-iframe-src.php	2018-05-12 04:11:16 UTC (rev 231730)
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script>
-if (window.testRunner) {
-    testRunner.dumpAsText();
-    testRunner.dumpChildFramesAsText();
-    testRunner.waitUntilDone();
-}
-</script>
-</head>
-<body>
-<iframe src="" echo $_GET['src']; ?>"></iframe>
-</body>
-</html>

Added: trunk/LayoutTests/http/tests/resources/echo-iframe-src.php (0 => 231730)


--- trunk/LayoutTests/http/tests/resources/echo-iframe-src.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/resources/echo-iframe-src.php	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.dumpChildFramesAsText();
+    testRunner.waitUntilDone();
+}
+</script>
+</head>
+<body>
+<iframe src="" echo $_GET['src']; ?>"></iframe>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-ancestors-same-origin-deny.html (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-ancestors-same-origin-deny.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-ancestors-same-origin-deny.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+function checkIfDone() {
+    try {
+        var url = ""
+        if (url)
+            console.log("FAIL: Could read contentWindow.location.href");
+        else
+            throw null;
+    } catch (e) {
+        if (e)
+            console.log(e);
+        console.log("PASS: Could not read contentWindow.location.href");
+    }
+    testRunner.notifyDone();
+}
+</script>
+</head>
+<body>
+<iframe src="" _onload_="checkIfDone()"></iframe>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -wT
+use strict;
+
+print "Content-Type: text/html\n";
+print "Cache-Control: no-cache, no-store\n";
+print "X-FRAME-OPTIONS: sameorigin\n\n";
+
+print <<"EOF";
+<p>PASS: This should show up as all frame ancestors are same origin with this page.</p>
+<script>
+if (window.testRunner)
+    testRunner.notifyDone();
+</script>
+EOF
Property changes on: trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-allow.cgi
___________________________________________________________________

Added: svn:executable

+* \ No newline at end of property

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,8 @@
+#!/usr/bin/perl -wT
+use strict;
+
+print "Content-Type: text/html\n";
+print "Cache-Control: no-cache, no-store\n";
+print "X-FRAME-OPTIONS: sameorigin\n\n";
+
+print "<p>FAIL: This should not show up as one or more frame ancestors are not same origin with this page.</p>\n";
Property changes on: trunk/LayoutTests/http/tests/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi
___________________________________________________________________

Added: svn:executable

+* \ No newline at end of property

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow-expected.txt (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow-expected.txt	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,11 @@
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+
+
+--------
+Frame: '<!--frame2-->'
+--------
+PASS: This should show up as all frame ancestors are same origin with this page.

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.dumpChildFramesAsText();
+    testRunner.waitUntilDone();
+}
+</script>
+</head>
+<head>
+<iframe src=""
+</head>
+</html>

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny-expected.txt (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny-expected.txt	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,14 @@
+CONSOLE MESSAGE: Refused to display 'http://127.0.0.1:8000/security/XFrameOptions/resources/x-frame-options-frame-ancestors-same-origin-deny.cgi' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
+CONSOLE MESSAGE: line 14: SecurityError: Sandbox access violation: Blocked a frame at "http://localhost:8000" from accessing a cross-origin frame.  The frame being accessed is sandboxed and lacks the "allow-same-origin" flag.
+CONSOLE MESSAGE: line 15: PASS: Could not read contentWindow.location.href
+
+
+--------
+Frame: '<!--frame1-->'
+--------
+
+
+--------
+Frame: '<!--frame2-->'
+--------
+

Added: trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html (0 => 231730)


--- trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html	2018-05-12 04:11:16 UTC (rev 231730)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.dumpChildFramesAsText();
+    testRunner.waitUntilDone();
+}
+</script>
+</head>
+<head>
+<iframe src=""
+</head>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (231729 => 231730)


--- trunk/Source/WebCore/ChangeLog	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/Source/WebCore/ChangeLog	2018-05-12 04:11:16 UTC (rev 231730)
@@ -1,5 +1,32 @@
 2018-05-11  Daniel Bates  <[email protected]>
 
+        X-Frame-Options: SAMEORIGIN needs to check all ancestor frames
+        https://bugs.webkit.org/show_bug.cgi?id=185567
+        <rdar://problem/40175008>
+
+        Reviewed by Brent Fulgham.
+
+        Change the behavior of "X-Frame-Options: SAMEORIGIN" to ensure that all ancestors frames
+        are same-origin with the document that delivered this header. This prevents an intermediary
+        malicious frame from clickjacking a child frame whose document is same-origin with the top-
+        level frame. It also makes the behavior of X-Frame-Options in WebKit more closely match
+        the behavior of X-Frame-Options in other browsers, including Chrome and Firefox.
+        
+        Currently a document delivered with "X-Frame-Options: SAMEORIGIN" must only be same-origin
+        with the top-level frame's document in order to be displayed. This prevents clickjacking by
+        a malicious page that embeds a page delivered with "X-Frame-Options: SAMEORIGIN". However,
+        it does not protect against clickjacking of the "X-Frame-Options: SAMEORIGIN" page (victim)
+        if embedded by an intermediate malicious iframe, say a "rogue ad", that was embedded in a
+        document same origin with the victim page. We should protect against such attacks. 
+
+        Tests: http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-allow.html
+               http/tests/security/XFrameOptions/x-frame-options-ancestors-same-origin-deny.html
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::shouldInterruptLoadForXFrameOptions):
+
+2018-05-11  Daniel Bates  <[email protected]>
+
         [iOS] Text decoration of dragged content does not paint with opacity
         https://bugs.webkit.org/show_bug.cgi?id=185551
         <rdar://problem/40166867>

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (231729 => 231730)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2018-05-12 04:11:16 UTC (rev 231730)
@@ -3420,7 +3420,7 @@
             return true;
         for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
-                break;
+                return true;
         }
         return false;
     }

Modified: trunk/Source/WebKit/ChangeLog (231729 => 231730)


--- trunk/Source/WebKit/ChangeLog	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/Source/WebKit/ChangeLog	2018-05-12 04:11:16 UTC (rev 231730)
@@ -1,3 +1,27 @@
+2018-05-11  Daniel Bates  <[email protected]>
+
+        X-Frame-Options: SAMEORIGIN needs to check all ancestor frames
+        https://bugs.webkit.org/show_bug.cgi?id=185567
+        <rdar://problem/40175008>
+
+        Reviewed by Brent Fulgham.
+
+        Change the behavior of "X-Frame-Options: SAMEORIGIN" to ensure that all ancestors frames
+        are same-origin with the document that delivered this header. This prevents an intermediary
+        malicious frame from clickjacking a child frame whose document is same-origin with the top-
+        level frame. It also makes the behavior of X-Frame-Options in WebKit more closely match
+        the behavior of X-Frame-Options in other browsers, including Chrome and Firefox.
+        
+        Currently a document delivered with "X-Frame-Options: SAMEORIGIN" must only be same-origin
+        with the top-level frame's document in order to be displayed. This prevents clickjacking by
+        a malicious page that embeds a page delivered with "X-Frame-Options: SAMEORIGIN". However,
+        it does not protect against clickjacking of the "X-Frame-Options: SAMEORIGIN" page (victim)
+        if embedded by an intermediate malicious iframe, say a "rogue ad", that was embedded in a
+        document same origin with the victim page. We should protect against such attacks.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::shouldInterruptLoadForXFrameOptions):
+
 2018-05-11  Dean Jackson  <[email protected]>
 
         WKWebViewContentProvider should know what MIME type it was created to handle

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (231729 => 231730)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2018-05-12 02:11:05 UTC (rev 231729)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2018-05-12 04:11:16 UTC (rev 231730)
@@ -414,8 +414,16 @@
         return false;
     case XFrameOptionsDeny:
         return true;
-    case XFrameOptionsSameOrigin:
-        return !SecurityOrigin::create(url)->isSameSchemeHostPort(*m_parameters.sourceOrigin);
+    case XFrameOptionsSameOrigin: {
+        auto origin = SecurityOrigin::create(url);
+        if (!origin->isSameSchemeHostPort(*m_parameters.sourceOrigin))
+            return true;
+        for (auto& ancestorOrigin : m_parameters.frameAncestorOrigins) {
+            if (!origin->isSameSchemeHostPort(*ancestorOrigin))
+                return true;
+        }
+        return false;
+    }
     case XFrameOptionsConflict: {
         String errorMessage = "Multiple 'X-Frame-Options' headers with conflicting values ('" + xFrameOptions + "') encountered when loading '" + url.stringCenterEllipsizedToLength() + "'. Falling back to 'DENY'.";
         send(Messages::WebPage::AddConsoleMessage { m_parameters.webFrameID,  MessageSource::JS, MessageLevel::Error, errorMessage, identifier() }, m_parameters.webPageID);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to