Commit 7e282a94 authored by Mustafa Emre Acer's avatar Mustafa Emre Acer Committed by Commit Bot

[Lookalike URLs] Test lookalike URL logic with signed exchanges

This CL adds a lookalike navigation browser test for signed exchanges.
The current lookalikes code blocks signed exchanges in both of the
following cases:
- The target URL of the SGX package is a lookalike
- The URL that serves the SGX is a lookalike

For the first case, the test navigates to a signed exchange URL that
serves a SGX for google-com.example.org and checks that the URL is
blocked by the target embedding heuristic. The second case serves the
SGX from google-com.example.org and checks that it's blocked.

There is an argument to be made for the latter case to not be blocked
since the URL that serves the SGX is never seen by the user during
normal browsing such as clicking links. However, there is still a chance
that such a URL is shared from outside Chrome (e.g. coming in an email).
We still want to block those cases.

Additionally, detecting that a navigation will end up as a SGX isn't
trivial as the SGX package needs to be fully validated before its
contents can be displayed. It might be too late to block the original
navigation by the time the SGX is validated. This needs to be confirmed
and might be changed in follow up CLs.

Bug: 1110151
Change-Id: I2b2e4841eb142b3f2d1c1cedf82138f578e770a4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2386429
Commit-Queue: Mustafa Emre Acer <meacer@chromium.org>
Reviewed-by: default avatarJoe DeBlasio <jdeblasio@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804412}
parent 64189c88
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
#include "components/security_interstitials/core/metrics_helper.h" #include "components/security_interstitials/core/metrics_helper.h"
#include "components/ukm/test_ukm_recorder.h" #include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h" #include "content/public/test/browser_test.h"
#include "content/public/test/signed_exchange_browser_test_helper.h"
#include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_navigation_observer.h"
#include "net/dns/mock_host_resolver.h" #include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_request.h"
...@@ -194,6 +196,7 @@ class LookalikeUrlNavigationThrottleBrowserTest ...@@ -194,6 +196,7 @@ class LookalikeUrlNavigationThrottleBrowserTest
base::FieldTrialParams params; base::FieldTrialParams params;
enabled_features.emplace_back( enabled_features.emplace_back(
lookalikes::features::kDetectTargetEmbeddingLookalikes, params); lookalikes::features::kDetectTargetEmbeddingLookalikes, params);
enabled_features.emplace_back(features::kSignedHTTPExchange, params);
} else { } else {
disabled_features.push_back( disabled_features.push_back(
lookalikes::features::kDetectTargetEmbeddingLookalikes); lookalikes::features::kDetectTargetEmbeddingLookalikes);
...@@ -1222,3 +1225,101 @@ IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest, ...@@ -1222,3 +1225,101 @@ IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleBrowserTest,
TestInterstitialNotShown(browser(), TestInterstitialNotShown(browser(),
embedded_test_server()->GetURL("example.net", "/")); embedded_test_server()->GetURL("example.net", "/"));
} }
// Tests for Signed Exchanges.
class LookalikeUrlNavigationThrottleSignedExchangeBrowserTest
: public LookalikeUrlNavigationThrottleBrowserTest {
public:
void SetUpOnMainThread() override {
sxg_test_helper_.SetUp();
embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&LookalikeUrlNavigationThrottleSignedExchangeBrowserTest::
MonitorRequest,
base::Unretained(this)));
LookalikeUrlNavigationThrottleBrowserTest::SetUpOnMainThread();
}
void TearDownOnMainThread() override {
sxg_test_helper_.TearDownOnMainThread();
}
bool HadSignedExchangeInAcceptHeader(const GURL& url) const {
const auto it = url_accept_header_map_.find(url);
if (it == url_accept_header_map_.end())
return false;
return it->second.find("application/signed-exchange") != std::string::npos;
}
protected:
content::SignedExchangeBrowserTestHelper sxg_test_helper_;
private:
void MonitorRequest(const net::test_server::HttpRequest& request) {
const auto it = request.headers.find("Accept");
if (it == request.headers.end())
return;
url_accept_header_map_[request.base_url.Resolve(request.relative_url)] =
it->second;
}
std::map<GURL, std::string> url_accept_header_map_;
};
INSTANTIATE_TEST_SUITE_P(
All,
LookalikeUrlNavigationThrottleSignedExchangeBrowserTest,
testing::Combine(testing::Bool(), testing::Bool()));
// Navigates to a 127.0.0.1 URL that serves a signed exchange for
// google-com.example.org. This navigation should be blocked by the target
// embedding interstitial. We only test target embedding here because we can
// test it with a subdomain of example.org (which is the domain used by SGX test
// code). Testing an ETLD+1 such as googlé.com would require generating a custom
// cert.
IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleSignedExchangeBrowserTest,
SignedExchange_ShouldBlockTarget) {
if (!target_embedding_enabled()) {
return;
}
sxg_test_helper_.InstallUrlInterceptor(
GURL("https://google-com.example.org/test/"),
"content/test/data/sxg/fallback.html");
const GURL kNavigatedUrl =
embedded_test_server()->GetURL("/sxg/google-com.example.org_test.sxg");
const GURL kExpectedSuggestedUrl("https://google.com");
TestMetricsRecordedAndInterstitialShown(
browser(), kNavigatedUrl, kExpectedSuggestedUrl,
NavigationSuggestionEvent::kMatchTargetEmbedding);
// Check that the SXG file was handled as a Signed Exchange.
ASSERT_TRUE(HadSignedExchangeInAcceptHeader(kNavigatedUrl));
}
// Navigates to a lookalike URL that serves a signed exchange for
// test.example.org. This should also be blocked by the lookalike interstitial,
// even though the URL that serves the signed exchange is never visible to
// the user.
IN_PROC_BROWSER_TEST_P(LookalikeUrlNavigationThrottleSignedExchangeBrowserTest,
SignedExchange_ShouldBlockCacheUrl) {
if (!target_embedding_enabled()) {
return;
}
const GURL kSgxTargetUrl("https://test.example.org/test/");
sxg_test_helper_.InstallUrlInterceptor(kSgxTargetUrl,
"content/test/data/sxg/fallback.html");
const GURL kNavigatedUrl = embedded_test_server()->GetURL(
"google-com.test.com", "/sxg/test.example.org_test.sxg");
const GURL kExpectedSuggestedUrl =
embedded_test_server()->GetURL("google.com", "/");
TestMetricsRecordedAndInterstitialShown(
browser(), kNavigatedUrl, kExpectedSuggestedUrl,
NavigationSuggestionEvent::kMatchTargetEmbedding);
// Check that no SXG response was handled.
ASSERT_FALSE(HadSignedExchangeInAcceptHeader(kNavigatedUrl));
ASSERT_FALSE(HadSignedExchangeInAcceptHeader(kSgxTargetUrl));
}
...@@ -65,6 +65,22 @@ gen-signedexchange \ ...@@ -65,6 +65,22 @@ gen-signedexchange \
-o test.example.org_test.sxg \ -o test.example.org_test.sxg \
-miRecordSize 100 -miRecordSize 100
# Generate the signed exchange file for google-com.example.org. This is used
# for lookalike URL testing.
gen-signedexchange \
-version 1b3 \
-uri https://google-com.example.org/test/ \
-status 200 \
-content test.html \
-certificate prime256v1-sha256.public.pem \
-certUrl https://cert.example.org/cert.msg \
-validityUrl https://google-com.example.org/resource.validity.msg \
-privateKey prime256v1.key \
-date $signature_date \
-expire 168h \
-o google-com.example.org_test.sxg \
-miRecordSize 100
# Generate the signed exchange for the missing nosniff header test case. # Generate the signed exchange for the missing nosniff header test case.
cp test.example.org_test.sxg test.example.org_test_missing_nosniff.sxg cp test.example.org_test.sxg test.example.org_test_missing_nosniff.sxg
......
HTTP/1.1 200 OK
Content-Type: application/signed-exchange;v=b3
X-Content-Type-Options: nosniff
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