Commit 07fbae50 authored by Mike West's avatar Mike West Committed by Commit Bot

Check ancestors when setting an <iframe> navigation's "site for cookies".

Currently, we're setting the "site for cookies" only by looking at the
top-level document. We ought to be verifying that the ancestor frames
are same-site before doing so. We do this correctly in Blink (see
`Document::SiteForCookies`), but didn't do so when navigating in the
browser.

This patch addresses the majority of the problem by walking the ancestor
chain when processing a NavigationRequest. If all the ancestors are
same-site, we set the "site for cookies" to the top-level document's URL.
If they aren't all same-site, we set it to an empty URL to ensure that
we don't send SameSite cookies.

Bug: 833847
Change-Id: Icd77f31fa618fa9f8b59fc3b15e1bed6ee05aabd
Reviewed-on: https://chromium-review.googlesource.com/1025772Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: Mike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553942}
parent 7a87e4e8
...@@ -1197,12 +1197,28 @@ void NavigationRequest::OnStartChecksComplete( ...@@ -1197,12 +1197,28 @@ void NavigationRequest::OnStartChecksComplete(
!base_url.is_empty() !base_url.is_empty()
? base_url ? base_url
: frame_tree_node_->frame_tree()->root()->current_url(); : frame_tree_node_->frame_tree()->root()->current_url();
// Walk the ancestor chain to determine whether all frames are same-site. If
// not, the |site_for_cookies| is set to an empty URL.
//
// TODO(mkwst): This is incorrect. It ought to use the definition from // TODO(mkwst): This is incorrect. It ought to use the definition from
// 'Document::firstPartyForCookies()' in Blink, which walks the ancestor tree // 'Document::SiteForCookies()' in Blink, which special-cases extension
// and verifies that all origins are PSL-matches (and special-cases extension // URLs and a few other sharp edges.
// URLs). const FrameTreeNode* current = frame_tree_node_->parent();
bool ancestors_are_same_site = true;
while (current && ancestors_are_same_site) {
if (!net::registry_controlled_domains::SameDomainOrHost(
top_document_url, current->current_url(),
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
ancestors_are_same_site = false;
}
current = current->parent();
}
const GURL& site_for_cookies = const GURL& site_for_cookies =
frame_tree_node_->IsMainFrame() ? common_params_.url : top_document_url; ancestors_are_same_site
? (frame_tree_node_->IsMainFrame() ? common_params_.url
: top_document_url)
: GURL::EmptyGURL();
bool parent_is_main_frame = !frame_tree_node_->parent() bool parent_is_main_frame = !frame_tree_node_->parent()
? false ? false
: frame_tree_node_->parent()->IsMainFrame(); : frame_tree_node_->parent()->IsMainFrame();
......
<!doctype html>
<body>
<iframe src="<?php
echo $_GET['url'];
?>"></iframe>
<!doctype html>
<script>
var from_http = <?php
echo json_encode($_COOKIE);
?>;
window.top.postMessage({
'http': from_http,
'document': document.cookie
}, "*");
</script>
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/cookies/resources/testharness-helpers.js"></script>
<body>
<script>
function addFrame(url) {
var i = document.createElement('iframe');
i.src = url;
document.body.appendChild(i);
return i;
}
// Set cookies on ORIGINAL_HOST, then move ourselves to TEST_ROOT so
// we can verify registrable domain and cross-origin behavior.
if (window.location.hostname == "127.0.0.1") {
window.location.hostname = ORIGINAL_HOST;
} else if (window.location.hostname == ORIGINAL_HOST) {
clearKnownCookies();
document.cookie = STRICT_DOM + "=1; SameSite=Strict; Max-Age=100; path=/";
document.cookie = LAX_DOM + "=1; SameSite=Lax; Max-Age=100; path=/";
document.cookie = NORMAL_DOM + "=1; Max-Age=100; path=/";
window.location.hostname = TEST_HOST;
} else {
test(_ => {
clearKnownCookies();
assert_equals(document.cookie, "");
document.cookie = STRICT_DOM + "=2; SameSite=Strict; domain=" + TEST_HOST + "; path=/";
document.cookie = LAX_DOM + "=2; SameSite=Lax; domain=" + TEST_HOST + "; path=/";
document.cookie = NORMAL_DOM + "=2; domain=" + TEST_HOST + "; path=/";
assert_equals(document.cookie, STRICT_DOM + "=2; " + LAX_DOM + "=2; " + NORMAL_DOM + "=2");
}, "Set cookies for TEST_HOST");
// Framed
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], "2", "strict http");
assert_equals(http_cookies[LAX_DOM], "2", "lax http");
assert_equals(http_cookies[NORMAL_DOM], "2", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, STRICT_DOM + "=2; " + LAX_DOM + "=2; " + NORMAL_DOM + "=2");
r();
};
frame = addFrame("https://" + TEST_HOST + ":8443/cookies/resources/post-cookies-to-top.php");
});
}, "Same-origin frame receives all SameSite cookies.");
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], undefined, "strict http");
assert_equals(http_cookies[LAX_DOM], undefined, "lax http");
assert_equals(http_cookies[NORMAL_DOM], "1", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, NORMAL_DOM + "=1");
r();
};
frame = addFrame("https://" + ORIGINAL_HOST + ":8443/cookies/resources/post-cookies-to-top.php");
});
}, "Cross-origin frame receives no SameSite cookies.");
// Nested Frames
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], "2", "strict http");
assert_equals(http_cookies[LAX_DOM], "2", "lax http");
assert_equals(http_cookies[NORMAL_DOM], "2", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, STRICT_DOM + "=2; " + LAX_DOM + "=2; " + NORMAL_DOM + "=2");
r();
};
frame = addFrame(
"https://" + TEST_HOST + ":8443/cookies/resources/frame.php?url=" +
encodeURIComponent("https://" + TEST_HOST + ":8443/cookies/resources/post-cookies-to-top.php")
);
});
}, "Same-origin frame nested in same-origin frame receives all SameSite cookies.");
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], undefined, "strict http");
assert_equals(http_cookies[LAX_DOM], undefined, "lax http");
assert_equals(http_cookies[NORMAL_DOM], "2", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, NORMAL_DOM + "=2");
r();
};
frame = addFrame(
"https://" + ORIGINAL_HOST + ":8443/cookies/resources/frame.php?url=" +
encodeURIComponent("https://" + TEST_HOST + ":8443/cookies/resources/post-cookies-to-top.php")
);
});
}, "Same-origin frame nested in cross-origin frame receives no SameSite cookies.");
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], undefined, "strict http");
assert_equals(http_cookies[LAX_DOM], undefined, "lax http");
assert_equals(http_cookies[NORMAL_DOM], "1", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, NORMAL_DOM + "=1");
r();
};
frame = addFrame(
"https://" + TEST_HOST + ":8443/cookies/resources/frame.php?url=" +
encodeURIComponent("https://" + ORIGINAL_HOST + ":8443/cookies/resources/post-cookies-to-top.php")
);
});
}, "Cross-origin frame nested in same-origin frame receives no SameSite cookies.");
promise_test(_ => {
var frame;
return new Promise(r => {
window.onmessage = e => {
var http_cookies = e.data.http;
assert_equals(http_cookies[STRICT_DOM], undefined, "strict http");
assert_equals(http_cookies[LAX_DOM], undefined, "lax http");
assert_equals(http_cookies[NORMAL_DOM], "1", "normal http");
var dom_cookies = e.data.document;
assert_equals(dom_cookies, NORMAL_DOM + "=1");
r();
};
frame = addFrame(
"https://" + ORIGINAL_HOST + ":8443/cookies/resources/frame.php?url=" +
encodeURIComponent("https://" + ORIGINAL_HOST + ":8443/cookies/resources/post-cookies-to-top.php")
);
});
}, "Cross-origin frame nested in cross-origin frame receives no SameSite cookies.");
}
</script>
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