Commit 56dc8e21 authored by estark's avatar estark Committed by Commit bot

Adapt MixedContentChecker for remote frames

This CL adapts MixedContentChecker to do correct mixed content checks
for content that is mixed with respect to a remote frame. There are a
couple caveats/behavior changes:

- When mixed content is detected, the message logged to the console is
  changed slightly: when the mixed frame is remote, it prints the origin
  instead of the full URL.
- Subresources loaded with certificate errors are not yet correctly
  treated as mixed content when they are loaded in a remote HTTPS parent
  frame.
- FrameLoaderClient methods, for the most part, go to the client for the
  frame that loaded the resource, which is not necessarily the "mixed
  frame". This is weird, but in practice, the implementations of these
  FrameLoaderClient methods do not care which frame they are actually
  called on.
BUG=486936

Review URL: https://codereview.chromium.org/1550723003

Cr-Commit-Position: refs/heads/master@{#371534}
parent 413e0b00
......@@ -368,6 +368,33 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
false /* expect cert status error */);
}
// Tests that the Content Security Policy block-all-mixed-content
// directive stops mixed content from running.
IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest,
MixedContentStrictBlocking) {
ASSERT_TRUE(https_server_.Start());
SetUpMockCertVerifierForHttpsServer(0, net::OK);
// Navigate to an HTTPS page that tries to run mixed content in an
// iframe, with strict mixed content blocking.
std::string replacement_path;
net::HostPortPair host_port_pair =
net::HostPortPair::FromURL(https_server_.GetURL("/"));
host_port_pair.set_host("different-host.test");
host_resolver()->AddRule("different-host.test",
https_server_.GetURL("/").host());
GetFilePathWithHostAndPortReplacement(
"/ssl/page_runs_insecure_content_in_iframe_with_strict_blocking.html",
host_port_pair, &replacement_path);
ui_test_utils::NavigateToURL(browser(),
https_server_.GetURL(replacement_path));
CheckSecurityInfoForSecure(
browser()->tab_strip_model()->GetActiveWebContents(),
SecurityStateModel::SECURE, SecurityStateModel::NO_DEPRECATED_SHA1,
SecurityStateModel::NO_MIXED_CONTENT,
false /* expect cert status error */);
}
IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, BrokenHTTPS) {
ASSERT_TRUE(embedded_test_server()->Start());
ASSERT_TRUE(https_server_.Start());
......
<html>
<head><title>Page that runs insecure content in an iframe with strict blocking</title></head>
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
<body>
This page contains an iframe which loads contents over an http connection,
which would cause insecure content when this page is loaded over https, but
mixed content is strictly blocked with CSP.<br>
<iframe src="https://REPLACE_WITH_HOST_AND_PORT/ssl/iframe_with_insecure_content.html"/>
</body>
</html>
......@@ -602,6 +602,20 @@ class SitePerProcessHighDPIBrowserTest : public SitePerProcessBrowserTest {
}
};
// SitePerProcessIgnoreCertErrorsBrowserTest
class SitePerProcessIgnoreCertErrorsBrowserTest
: public SitePerProcessBrowserTest {
public:
SitePerProcessIgnoreCertErrorsBrowserTest() {}
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
SitePerProcessBrowserTest::SetUpCommandLine(command_line);
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
};
// Ensure that navigating subframes in --site-per-process mode works and the
// correct documents are committed.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
......@@ -4984,4 +4998,104 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(b_url.GetOrigin().spec(), popup_origin + "/");
}
// Tests that the WebContents is notified when passive mixed content is
// displayed in an OOPIF. The test ignores cert errors so that an HTTPS
// iframe can be loaded from a site other than localhost (the
// EmbeddedTestServer serves a certificate that is valid for localhost).
IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
PassiveMixedContentInIframe) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
GURL iframe_url(
https_server.GetURL("/mixed-content/basic-passive-in-iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url));
EXPECT_TRUE(shell()->web_contents()->DisplayedInsecureContent());
// When the subframe navigates, the WebContents should still be marked
// as having displayed insecure content.
GURL navigate_url(https_server.GetURL("/title1.html"));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
NavigateFrameToURL(root->child_at(0), navigate_url);
EXPECT_TRUE(shell()->web_contents()->DisplayedInsecureContent());
// When the main frame navigates, it should no longer be marked as
// displaying insecure content.
EXPECT_TRUE(
NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
}
// Tests that, when a parent frame is set to strictly block mixed
// content via Content Security Policy, child OOPIFs cannot display
// mixed content.
IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
PassiveMixedContentInIframeWithStrictBlocking) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
GURL iframe_url_with_strict_blocking(https_server.GetURL(
"/mixed-content/basic-passive-in-iframe-with-strict-blocking.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url_with_strict_blocking));
EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
EXPECT_TRUE(root->current_replication_state()
.should_enforce_strict_mixed_content_checking);
EXPECT_TRUE(root->child_at(0)
->current_replication_state()
.should_enforce_strict_mixed_content_checking);
// When the subframe navigates, it should still be marked as enforcing
// strict mixed content.
GURL navigate_url(https_server.GetURL("/title1.html"));
NavigateFrameToURL(root->child_at(0), navigate_url);
EXPECT_TRUE(root->current_replication_state()
.should_enforce_strict_mixed_content_checking);
EXPECT_TRUE(root->child_at(0)
->current_replication_state()
.should_enforce_strict_mixed_content_checking);
// When the main frame navigates, it should no longer be marked as
// enforcing strict mixed content.
EXPECT_TRUE(
NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
EXPECT_FALSE(root->current_replication_state()
.should_enforce_strict_mixed_content_checking);
}
// Tests that active mixed content is blocked in an OOPIF. The test
// ignores cert errors so that an HTTPS iframe can be loaded from a site
// other than localhost (the EmbeddedTestServer serves a certificate
// that is valid for localhost).
IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
ActiveMixedContentInIframe) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server.Start());
SetupCrossSiteRedirector(&https_server);
GURL iframe_url(
https_server.GetURL("/mixed-content/basic-active-in-iframe.html"));
EXPECT_TRUE(NavigateToURL(shell(), iframe_url));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* mixed_child = root->child_at(0)->child_at(0);
ASSERT_TRUE(mixed_child);
// The child iframe attempted to create a mixed iframe; this should
// have been blocked, so the mixed iframe should not have committed a
// load.
EXPECT_FALSE(mixed_child->has_committed_real_load());
}
} // namespace content
......@@ -375,6 +375,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameReplicationState)
IPC_STRUCT_TRAITS_MEMBER(origin)
IPC_STRUCT_TRAITS_MEMBER(sandbox_flags)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(scope)
IPC_STRUCT_TRAITS_MEMBER(should_enforce_strict_mixed_content_checking)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(FrameMsg_NewFrame_WidgetParams)
......
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
<iframe src="/cross-site/a.com/mixed-content/basic-active.html"></iframe>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<iframe src="http://a.test"></iframe>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
<body>
<iframe src="/cross-site/a.com/mixed-content/basic-passive.html"></iframe>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<iframe src="/cross-site/a.com/mixed-content/basic-passive.html"></iframe>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
This page tries to load some passive mixed content.
<img src="http://a.test/image.jpg" />
</body>
</html>
CONSOLE ERROR: line 4: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://127.0.0.1:8080/security/mixedContent/resources/style.css'. This request has been blocked; the content must be served over HTTPS.
CONSOLE ERROR: line 4: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/active-subresource-in-iframe-blocked.https.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://127.0.0.1:8080/security/mixedContent/resources/style.css'. This request has been blocked; the content must be served over HTTPS.
This test passes if the active subresource in the frame below is blocked.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
CONSOLE MESSAGE: line 12: Reloading...
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This content should also be served over HTTPS.
CONSOLE MESSAGE: line 17: Second load finished.
This test opens a window that loads a frame with a subframe which contains insecure css image. The subframe is refreshed after it loads. We should trigger a mixed content callback twice despite the fact that on a second load of the subframe a css cache might be used to fetch an image.
CONSOLE ERROR: line 1: Mixed Content: The page at 'data:text/html,<html><iframe src='http://127.0.0.1:8080/security/mixedContent/resources/boring.html'></iframe></html>' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This request has been blocked; the content must be served over HTTPS.
CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-data-url-frame-with-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This request has been blocked; the content must be served over HTTPS.
This test opens a window that loads a data: iframe that loads an insecure frame, and that the frame is still blocked.
CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
This test loads a secure iframe that loads an insecure iframe. We should get a mixed content callback becase the child frame is HTTPS.
CONSOLE WARNING: line 9: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-iframe.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-iframe.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
This test opens a window that loads an insecure iframe. We should trigger a mixed content callback even though we've set the preference to block this, because we've overriden the preference via a web permission client callback.
CONSOLE ERROR: line 9: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-iframe.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This request has been blocked; the content must be served over HTTPS.
CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-iframe.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This request has been blocked; the content must be served over HTTPS.
This test opens a window that loads an insecure iframe. We should not trigger a mixed content callback even though the main frame in the window is HTTPS and is displaying insecure content, because we've set the preference to block this.
CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
This test opens a window that loads an insecure iframe. We should trigger a mixed content callback because the main frame in the window is HTTPS but is running insecure content.
============== Back Forward List ==============
......
CONSOLE ERROR: Mixed Content: The page at 'data:text/html,<html><script src='http://127.0.0.1:8080/security/mixedContent/resources/script.js'></script></html>' was loaded over HTTPS, but requested an insecure script 'http://127.0.0.1:8080/security/mixedContent/resources/script.js'. This request has been blocked; the content must be served over HTTPS.
CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-data-url-frame-with-script.html' was loaded over HTTPS, but requested an insecure script 'http://127.0.0.1:8080/security/mixedContent/resources/script.js'. This request has been blocked; the content must be served over HTTPS.
This test opens a window that loads a data: iframe that loads an insecure script, and that the script is still blocked. Although the data: frame has a separate origin, the script can still navigate top.
CONSOLE WARNING: line 16: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https.html' was loaded over HTTPS, but requested an insecure resource 'nonwebbyscheme://this-will-fail-but-no-mixed-content-error-should-appear'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https.html' was loaded over HTTPS, but requested an insecure resource 'nonwebbyscheme://this-will-fail-but-no-mixed-content-error-should-appear'. This content should also be served over HTTPS.
This tests that non-webby URLs are not blocked as mixed content. The test passes if a mixed content warning is displayed and the load proceeds. The test fails if a mixed content error is displayed, and the load is blocked.
......
CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://127.0.0.1:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS.
This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-image.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This request has been blocked; the content must be served over HTTPS.
CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-image-in-frame-blocked.https.html' was loaded over HTTPS, but requested an insecure image 'http://127.0.0.1:8080/security/resources/compass.jpg'. This request has been blocked; the content must be served over HTTPS.
This test passes if the image in the frame below is treated as blockable content.
......@@ -203,8 +203,6 @@ void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const Mes
String sourceOrigin = sourceDocument->securityOrigin()->toString();
String sourceSuborigin = sourceDocument->securityOrigin()->suboriginName();
// FIXME: MixedContentChecker needs to be refactored for OOPIF. For now,
// create the url using replicated origins for remote frames.
KURL targetUrl = isLocalDOMWindow() ? document()->url() : KURL(KURL(), frame()->securityContext()->securityOrigin()->toString());
if (MixedContentChecker::isMixedContent(sourceDocument->securityOrigin(), targetUrl))
UseCounter::count(frame(), UseCounter::PostMessageFromSecureToInsecure);
......
......@@ -565,7 +565,7 @@ ResourceRequestBlockedReason FrameFetchContext::canRequestInternal(Resource::Typ
// They'll still get a warning in the console about CSP blocking the load.
MixedContentChecker::ReportingStatus mixedContentReporting = forPreload ?
MixedContentChecker::SuppressReport : MixedContentChecker::SendReport;
if (MixedContentChecker::shouldBlockFetch(MixedContentChecker::effectiveFrameForFrameType(frame(), resourceRequest.frameType()), resourceRequest, url, mixedContentReporting))
if (MixedContentChecker::shouldBlockFetch(frame(), resourceRequest, url, mixedContentReporting))
return ResourceRequestBlockedReasonMixedContent;
return ResourceRequestBlockedReasonNone;
......
......@@ -40,6 +40,7 @@
namespace blink {
class Frame;
class FrameLoaderClient;
class LocalFrame;
class KURL;
......@@ -75,7 +76,7 @@ public:
// Returns the frame that should be considered the effective frame
// for a mixed content check for the given frame type.
static LocalFrame* effectiveFrameForFrameType(LocalFrame*, WebURLRequest::FrameType);
static Frame* effectiveFrameForFrameType(LocalFrame*, WebURLRequest::FrameType);
static void handleCertificateError(LocalFrame*, const ResourceRequest&, const ResourceResponse&);
......@@ -88,13 +89,13 @@ private:
Submission
};
static LocalFrame* inWhichFrameIsContentMixed(LocalFrame*, WebURLRequest::FrameType, const KURL&);
static Frame* inWhichFrameIsContentMixed(Frame*, WebURLRequest::FrameType, const KURL&);
static ContextType contextTypeFromContext(WebURLRequest::RequestContext, LocalFrame*);
static ContextType contextTypeFromContext(WebURLRequest::RequestContext, Frame*);
static const char* typeNameFromContext(WebURLRequest::RequestContext);
static void logToConsoleAboutFetch(LocalFrame*, const KURL&, WebURLRequest::RequestContext, bool allowed);
static void logToConsoleAboutWebSocket(LocalFrame*, const KURL&, bool allowed);
static void count(LocalFrame*, WebURLRequest::RequestContext);
static void logToConsoleAboutFetch(LocalFrame*, const KURL&, const KURL&, WebURLRequest::RequestContext, bool allowed);
static void logToConsoleAboutWebSocket(LocalFrame*, const KURL&, const KURL&, bool allowed);
static void count(Frame*, WebURLRequest::RequestContext);
};
} // namespace blink
......
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