Commit 32ba6d46 authored by Nate Chapin's avatar Nate Chapin Committed by Commit Bot

Make cross origin fragment navigation timing attack defenses testable via internals API

This removes the need for dumpFrameLoadCallbacks(), which is difficult to make
consistent with and without site isolation

Bug: 619662
Change-Id: I94a553707c306eae4a755a2b2d3ddf45fa145bf7
Reviewed-on: https://chromium-review.googlesource.com/c/1354574Reviewed-by: default avatarMike West <mkwst@chromium.org>
Commit-Queue: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613184}
parent 0400dfb6
...@@ -471,6 +471,15 @@ int Internals::getResourcePriority(const String& url, Document* document) { ...@@ -471,6 +471,15 @@ int Internals::getResourcePriority(const String& url, Document* document) {
return static_cast<int>(resource->GetResourceRequest().Priority()); return static_cast<int>(resource->GetResourceRequest().Priority());
} }
bool Internals::doesWindowHaveUrlFragment(DOMWindow* window) {
if (window->IsRemoteDOMWindow())
return false;
return ToLocalFrame(window->GetFrame())
->GetDocument()
->Url()
.HasFragmentIdentifier();
}
String Internals::getResourceHeader(const String& url, String Internals::getResourceHeader(const String& url,
const String& header, const String& header,
Document* document) { Document* document) {
......
...@@ -108,6 +108,8 @@ class Internals final : public ScriptWrappable { ...@@ -108,6 +108,8 @@ class Internals final : public ScriptWrappable {
int getResourcePriority(const String& url, Document*); int getResourcePriority(const String& url, Document*);
String getResourceHeader(const String& url, const String& header, Document*); String getResourceHeader(const String& url, const String& header, Document*);
bool doesWindowHaveUrlFragment(DOMWindow*);
CSSStyleDeclaration* computedStyleIncludingVisitedInfo(Node*) const; CSSStyleDeclaration* computedStyleIncludingVisitedInfo(Node*) const;
void setBrowserControlsState(float top_height, void setBrowserControlsState(float top_height,
......
...@@ -44,6 +44,8 @@ enum EffectiveConnectionType { ...@@ -44,6 +44,8 @@ enum EffectiveConnectionType {
unsigned long getResourcePriority (DOMString url, Document document); unsigned long getResourcePriority (DOMString url, Document document);
DOMString getResourceHeader (DOMString url, DOMString header, Document document); DOMString getResourceHeader (DOMString url, DOMString header, Document document);
bool doesWindowHaveUrlFragment(Window window);
CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node); CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);
ShadowRoot createUserAgentShadowRoot(Element host); ShadowRoot createUserAgentShadowRoot(Element host);
......
...@@ -147,10 +147,6 @@ crbug.com/771003 virtual/outofblink-cors/http/tests/security/mixedContent/insecu ...@@ -147,10 +147,6 @@ crbug.com/771003 virtual/outofblink-cors/http/tests/security/mixedContent/insecu
crbug.com/393285 http/tests/text-autosizing/narrow-iframe.html [ Failure Crash ] crbug.com/393285 http/tests/text-autosizing/narrow-iframe.html [ Failure Crash ]
crbug.com/393285 http/tests/text-autosizing/wide-iframe.html [ Failure Crash ] crbug.com/393285 http/tests/text-autosizing/wide-iframe.html [ Failure Crash ]
# Console message differences (e.g. full URI vs origin-only): # Console message differences (e.g. full URI vs origin-only):
crbug.com/619662 http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/outofblink-cors-ns/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/outofblink-cors/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/619662 virtual/stable/http/tests/navigation/cross-origin-fragment-navigation-is-async.html [ Failure ]
crbug.com/669083 http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] crbug.com/669083 http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
crbug.com/669083 virtual/outofblink-cors-ns/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] crbug.com/669083 virtual/outofblink-cors-ns/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
crbug.com/669083 virtual/outofblink-cors/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ] crbug.com/669083 virtual/outofblink-cors/http/tests/security/frameNavigation/xss-DENIED-top-navigation-without-user-gesture.html [ Failure ]
......
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: ALERT: PASS: url fragment is changing asynchronously
frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
main frame - didReceiveTitle:
main frame - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
main frame - didHandleOnloadEventsForFrame
main frame - didFinishLoadForFrame
ALERT: PASS: scheduled postMessage() before hashchange triggered. ALERT: PASS: scheduled postMessage() before hashchange triggered.
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
ALERT: PASS: hashchange triggered after postMessage(). ALERT: PASS: hashchange triggered after postMessage().
This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the frame load callback for the load's commit will happen before the message is handled. This isn't as flaky as it sounds, though it does rely on this postMessage behavior (which seems reasonable to do). This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
This test passes if the didChangeLocationWithinPageForFrame callback fires after the postMessage alert() fires.
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<head> <head>
<script> <script>
if (window.testRunner) { if (window.testRunner) {
testRunner.dumpFrameLoadCallbacks();
testRunner.dumpAsText(); testRunner.dumpAsText();
testRunner.waitUntilDone(); testRunner.waitUntilDone();
} }
...@@ -11,6 +10,12 @@ ...@@ -11,6 +10,12 @@
function testFragmentNavigation() { function testFragmentNavigation() {
window.postMessage("postmessage", "*"); window.postMessage("postmessage", "*");
document.querySelector('iframe').src = "http://localhost:8000/navigation/resources/postmessage-on-hashchange.html#anchor1"; document.querySelector('iframe').src = "http://localhost:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
if (window.internals) {
if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
alert("FAIL: url fragment should change asynchronously");
else
alert("PASS: url fragment is changing asynchronously");
}
} }
var receivedScheduledPostMessage = false; var receivedScheduledPostMessage = false;
...@@ -36,11 +41,8 @@ ...@@ -36,11 +41,8 @@
<body> <body>
<p>This tests that cross-origin fragment navigations are asynchronous. It does <p>This tests that cross-origin fragment navigations are asynchronous. It does
so by scheduling a postMessage before scheduling the navigation. If the so by scheduling a postMessage before scheduling the navigation. If the
navigation is synchronous, the frame load callback for the load's commit will navigation is synchronous, the internals API will be able to report the presence
happen before the message is handled. This isn't as flaky as it sounds, though of an url fragment immediately.</p>
it does rely on this postMessage behavior (which seems reasonable to do).</p>
<p>This test passes if the didChangeLocationWithinPageForFrame callback
fires after the postMessage alert() fires.</p>
<iframe src="http://localhost:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe> <iframe src="http://localhost:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
</body> </body>
</html> </html>
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: ALERT: PASS: url fragment has changed synchronously
frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame
main frame - didReceiveTitle:
main frame - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle:
frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
frame "<!--framePath //<!--frame0-->-->" - didFinishLoadForFrame
main frame - didHandleOnloadEventsForFrame
main frame - didFinishLoadForFrame
ALERT: PASS: scheduled postMessage() before hashchange triggered. ALERT: PASS: scheduled postMessage() before hashchange triggered.
ALERT: PASS: hashchange triggered after postMessage(). ALERT: PASS: hashchange triggered after postMessage().
This tests that same-origin fragment navigations are synchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the frame load callback for the load's commit will happen before the message is handled. This isn't as flaky as it sounds, though it does rely on this postMessage behavior (which seems reasonable to do). This tests that same-origin fragment navigations are synchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
This test passes if the didChangeLocationWithinPageForFrame callback fires before the postMessage alert() fires.
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
<head> <head>
<script> <script>
if (window.testRunner) { if (window.testRunner) {
testRunner.dumpFrameLoadCallbacks();
testRunner.dumpAsText(); testRunner.dumpAsText();
testRunner.waitUntilDone(); testRunner.waitUntilDone();
} }
...@@ -11,6 +10,12 @@ ...@@ -11,6 +10,12 @@
function testFragmentNavigation() { function testFragmentNavigation() {
window.postMessage("postmessage", "*"); window.postMessage("postmessage", "*");
document.querySelector('iframe').src = "http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html#anchor1"; document.querySelector('iframe').src = "http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
if (window.internals) {
if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
alert("PASS: url fragment has changed synchronously");
else
alert("FAIL: url fragment should change synchronously");
}
} }
var receivedScheduledPostMessage = false; var receivedScheduledPostMessage = false;
...@@ -36,11 +41,8 @@ ...@@ -36,11 +41,8 @@
<body> <body>
<p>This tests that same-origin fragment navigations are synchronous. It does <p>This tests that same-origin fragment navigations are synchronous. It does
so by scheduling a postMessage before scheduling the navigation. If the so by scheduling a postMessage before scheduling the navigation. If the
navigation is synchronous, the frame load callback for the load's commit will navigation is synchronous, the internals API will be able to report the presence
happen before the message is handled. This isn't as flaky as it sounds, though of an url fragment immediately.</p>
it does rely on this postMessage behavior (which seems reasonable to do).</p>
<p>This test passes if the didChangeLocationWithinPageForFrame callback
fires before the postMessage alert() fires.</p>
<iframe src="http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe> <iframe src="http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
</body> </body>
</html> </html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment