Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove cross-origin .onion origins from location.ancestorOrigins #20622

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ class BraveSiteHacksNetworkDelegateBrowserTest : public InProcessBrowserTest {
"foobar.onion",
"/server-redirect-307?" + reflect_referrer_same_origin_url_.spec());
images_url_ = https_server_.GetURL("foobar.onion", "/referrer_images.html");

iframe_inner_url_ = https_server_.GetURL("a.com", "/reflect-referrer.html");
iframe_outer_url_ = https_server_.GetURL("a.com", "/iframe_load.html");
onion_iframe_inner_url_ =
https_server_.GetURL("foobar.onion", "/reflect-referrer.html");
onion_iframe_outer_url_ =
https_server_.GetURL("foobar.onion", "/iframe_load.html");
}

void HandleRequest(const net::test_server::HttpRequest& request) {
Expand Down Expand Up @@ -177,6 +184,11 @@ class BraveSiteHacksNetworkDelegateBrowserTest : public InProcessBrowserTest {
return images_url().ReplaceComponents(replacements);
}

const GURL& iframe_inner_url() { return iframe_inner_url_; }
const GURL& iframe_outer_url() { return iframe_outer_url_; }
const GURL& onion_iframe_inner_url() { return onion_iframe_inner_url_; }
const GURL& onion_iframe_outer_url() { return onion_iframe_outer_url_; }

const std::string& last_referrer(const GURL& url) {
base::AutoLock auto_lock(last_headers_lock_);
GURL::Replacements replacements;
Expand Down Expand Up @@ -226,6 +238,10 @@ class BraveSiteHacksNetworkDelegateBrowserTest : public InProcessBrowserTest {
GURL reflect_referrer_same_origin_url_;
GURL reflect_referrer_same_origin_redirect_url_;
GURL images_url_;
GURL iframe_inner_url_;
GURL iframe_outer_url_;
GURL onion_iframe_inner_url_;
GURL onion_iframe_outer_url_;
std::map<GURL, std::string> last_referrer_;
std::map<GURL, std::string> last_origin_;
mutable base::Lock last_headers_lock_;
Expand Down Expand Up @@ -488,4 +504,63 @@ IN_PROC_BROWSER_TEST_F(BraveSiteHacksNetworkDelegateBrowserTest,
EXPECT_EQ(last_referrer(image_url("8")), "");
EXPECT_EQ(last_origin(image_url("8")), "null");
}

IN_PROC_BROWSER_TEST_F(BraveSiteHacksNetworkDelegateBrowserTest,
OnionAncestorOrigins) {
net::ProxyConfigServiceTor::SetBypassTorProxyConfigForTesting(true);
tor::TorNavigationThrottle::SetSkipWaitForTorConnectedForTesting(true);
Browser* tor_browser =
TorProfileManager::SwitchToTorProfile(browser()->profile());

// Same-origin .onion iframes
{
const GURL inner_url = onion_iframe_inner_url();
const GURL same_origin_test_url = url(inner_url, onion_iframe_outer_url());
NavigateToURLAndWaitForRedirects(tor_browser, same_origin_test_url,
same_origin_test_url);
EXPECT_EQ(last_referrer(inner_url), same_origin_test_url.spec());

content::RenderFrameHost* inner_frame =
ChildFrameAt(contents(tor_browser)->GetPrimaryMainFrame(), 0);
std::string real_value =
content::EvalJs(inner_frame, "getAncestors()").ExtractString();
std::string onion_origin =
url::Origin::Create(onion_iframe_outer_url()).GetURL().spec();
onion_origin.pop_back(); // remove trailing slash
EXPECT_EQ(real_value, "[" + onion_origin + "]");
}

// Cross-origin .onion outer iframe
{
const GURL inner_url = iframe_inner_url();
const GURL cross_origin_test_url = url(inner_url, onion_iframe_outer_url());
NavigateToURLAndWaitForRedirects(tor_browser, cross_origin_test_url,
cross_origin_test_url);
EXPECT_EQ(last_referrer(inner_url), "");

content::RenderFrameHost* inner_frame =
ChildFrameAt(contents(tor_browser)->GetPrimaryMainFrame(), 0);
std::string real_value =
content::EvalJs(inner_frame, "getAncestors()").ExtractString();
EXPECT_EQ(real_value, "[\"null\"]");
}

// Cross-origin .onion inner iframe
{
const GURL inner_url = onion_iframe_inner_url();
const GURL cross_origin_test_url = url(inner_url, iframe_outer_url());
NavigateToURLAndWaitForRedirects(tor_browser, cross_origin_test_url,
cross_origin_test_url);
std::string iframe_origin =
url::Origin::Create(iframe_outer_url()).GetURL().spec();
EXPECT_EQ(last_referrer(inner_url), iframe_origin);

content::RenderFrameHost* inner_frame =
ChildFrameAt(contents(tor_browser)->GetPrimaryMainFrame(), 0);
std::string real_value =
content::EvalJs(inner_frame, "getAncestors()").ExtractString();
iframe_origin.pop_back(); // remove trailing slash
EXPECT_EQ(real_value, "[" + iframe_origin + "]");
}
}
#endif
39 changes: 39 additions & 0 deletions chromium_src/third_party/blink/renderer/core/frame/location.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* Copyright (c) 2023 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "third_party/blink/renderer/core/frame/location.h"

#define ancestorOrigins ancestorOrigins_ChromiumImpl
#include "src/third_party/blink/renderer/core/frame/location.cc"
#undef ancestorOrigins

namespace blink {

DOMStringList* Location::ancestorOrigins() const {
auto* filtered_origins = MakeGarbageCollected<DOMStringList>();
const auto* innermost_origin =
DomWindow()->GetFrame()->GetSecurityContext()->GetSecurityOrigin();

auto is_onion_service = [](const SecurityOrigin* origin) {
return origin->Host().EndsWith(".onion", kTextCaseASCIIInsensitive);
};

auto* raw_origins = ancestorOrigins_ChromiumImpl();
for (uint32_t i = 0; i < raw_origins->length(); ++i) {
const String raw_origin = raw_origins->item(i);
const scoped_refptr<SecurityOrigin> origin =
SecurityOrigin::CreateFromString(raw_origin);
if (is_onion_service(origin.get()) &&
!origin->IsSameOriginWith(innermost_origin)) {
filtered_origins->Append("\"null\"");
} else {
filtered_origins->Append(raw_origin);
}
}

return filtered_origins;
}

} // namespace blink
17 changes: 17 additions & 0 deletions chromium_src/third_party/blink/renderer/core/frame/location.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* Copyright (c) 2023 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_H_
#define BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_H_

#define ancestorOrigins() \
ancestorOrigins_ChromiumImpl() const; \
DOMStringList* ancestorOrigins()

#include "src/third_party/blink/renderer/core/frame/location.h" // IWYU pragma: export

#undef ancestorOrigins

#endif // BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LOCATION_H_
13 changes: 13 additions & 0 deletions test/data/iframe_load.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<html><head><title>iframe test</title></head>
<body>
<iframe src="about:blank" id="test"></iframe>
<script>
function requestedUrl() {
const urlParams = new URLSearchParams(window.location.search);
const url = urlParams.get('url');
return atob(url);
}
var iframe = document.getElementById("test");
iframe.src = requestedUrl();
</script>
</body></html>
12 changes: 12 additions & 0 deletions test/data/reflect-referrer.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
<html>
<body>
<p>Referrer (JS): <code id="referrer"></code></p>
<p>AncestorOrigins (JS): <code id="ancestors"></code></p>
<script>

function getAncestors() {
let a = "";
for (origin of document.location.ancestorOrigins) {
a += '[' + origin + ']';
}
return a;
}

var referrer = document.getElementById("referrer");
referrer.innerText = document.referrer;
var ancestors = document.getElementById("ancestors");
ancestors.innerText = getAncestors();
</script>
</body>
</html>