Commit 7614790c authored by Charlie Reis's avatar Charlie Reis Committed by Commit Bot

Apply ExtensionNavigationThrottle filesystem/blob checks to all frames.

BUG=836858

Change-Id: I34333a72501129fd40b5a9aa6378c9f35f1e7fc2
Reviewed-on: https://chromium-review.googlesource.com/1028511Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Reviewed-by: default avatarNick Carter <nick@chromium.org>
Commit-Queue: Charlie Reis <creis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553867}
parent b9b0b6c2
......@@ -923,6 +923,73 @@ IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
}
}
// Test that navigations to blob: and filesystem: URLs with extension origins
// are disallowed in subframes when initiated from non-extension processes, even
// when the main frame lies about its origin. See https://crbug.com/836858.
IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
NestedURLNavigationsToExtensionBlockedInSubframe) {
// Disabling web security is necessary to test the browser enforcement;
// without it, the loads in this test would be blocked by
// SecurityOrigin::canDisplay() as invalid local resource loads.
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetBoolean(prefs::kWebKitWebSecurityEnabled, false);
// Create a simple extension without a background page.
const Extension* extension = CreateExtension("Extension", false);
embedded_test_server()->ServeFilesFromDirectory(extension->path());
ASSERT_TRUE(embedded_test_server()->Start());
// Navigate main tab to a web page with two web iframes. There should be no
// extension frames yet.
NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html"));
ProcessManager* pm = ProcessManager::Get(profile());
EXPECT_EQ(0u, pm->GetAllFrames().size());
EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
// Navigate first subframe to an extension URL. This will go into a new
// extension process.
const GURL extension_url(extension->url().Resolve("empty.html"));
EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame1", extension_url));
EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
EXPECT_EQ(1u, pm->GetAllFrames().size());
content::RenderFrameHost* main_frame = tab->GetMainFrame();
content::RenderFrameHost* extension_frame = ChildFrameAt(main_frame, 0);
// Create valid blob and filesystem URLs in the extension's origin.
url::Origin extension_origin(extension_frame->GetLastCommittedOrigin());
GURL blob_url(CreateBlobURL(extension_frame, "foo"));
EXPECT_EQ(extension_origin, url::Origin::Create(blob_url));
GURL filesystem_url(CreateFileSystemURL(extension_frame, "foo"));
EXPECT_EQ(extension_origin, url::Origin::Create(filesystem_url));
// Suppose that the main frame's origin incorrectly claims it is an extension,
// even though it is not in an extension process. This used to bypass the
// checks in ExtensionNavigationThrottle.
OverrideLastCommittedOrigin(main_frame, extension_origin);
// Navigate second subframe to each nested URL from the main frame (i.e.,
// from non-extension process). These should be canceled.
GURL nested_urls[] = {blob_url, filesystem_url};
for (size_t i = 0; i < arraysize(nested_urls); i++) {
EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame2", nested_urls[i]));
content::RenderFrameHost* second_frame = ChildFrameAt(main_frame, 1);
EXPECT_NE(nested_urls[i], second_frame->GetLastCommittedURL());
EXPECT_FALSE(extension_origin.IsSameOriginWith(
second_frame->GetLastCommittedOrigin()));
EXPECT_NE("foo", GetTextContent(second_frame));
EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
EXPECT_EQ(1u, pm->GetAllFrames().size());
EXPECT_TRUE(
content::NavigateIframeToURL(tab, "frame2", GURL(url::kAboutBlankURL)));
}
}
// Test that navigations to blob: and filesystem: URLs with extension origins
// are allowed when initiated from extension processes. See
// https://crbug.com/645028 and https://crbug.com/644426.
......
......@@ -1444,6 +1444,11 @@ void RenderFrameHostImpl::SetLastCommittedOrigin(const url::Origin& origin) {
CSPContext::SetSelf(origin);
}
void RenderFrameHostImpl::SetLastCommittedOriginForTesting(
const url::Origin& origin) {
SetLastCommittedOrigin(origin);
}
void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
last_committed_url_ = url;
}
......
......@@ -338,6 +338,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// cases, use GetLastCommittedURL instead.
const GURL& last_successful_url() { return last_successful_url_; }
// Allows overriding the last committed origin in tests.
void SetLastCommittedOriginForTesting(const url::Origin& origin);
// Fetch the link-rel canonical URL to be used for sharing to external
// applications.
void GetCanonicalUrlForSharing(
......
......@@ -626,6 +626,12 @@ bool IsLastCommittedEntryOfPageType(WebContents* web_contents,
return last_entry->GetPageType() == page_type;
}
void OverrideLastCommittedOrigin(RenderFrameHost* render_frame_host,
const url::Origin& origin) {
static_cast<RenderFrameHostImpl*>(render_frame_host)
->SetLastCommittedOriginForTesting(origin);
}
void CrashTab(WebContents* web_contents) {
RenderProcessHost* rph = web_contents->GetMainFrame()->GetProcess();
RenderProcessHostWatcher watcher(
......
......@@ -121,6 +121,12 @@ void PrepContentsForBeforeUnloadTest(WebContents* web_contents);
void WaitForResizeComplete(WebContents* web_contents);
#endif // defined(USE_AURA) || defined(OS_ANDROID)
// Allows tests to set the last committed origin of |render_frame_host|, to
// simulate a scenario that might happen with a compromised renderer or might
// not otherwise be possible.
void OverrideLastCommittedOrigin(RenderFrameHost* render_frame_host,
const url::Origin& origin);
// Causes the specified web_contents to crash. Blocks until it is crashed.
void CrashTab(WebContents* web_contents);
......
......@@ -77,30 +77,31 @@ ExtensionNavigationThrottle::WillStartOrRedirectRequest() {
}
}
if (navigation_handle()->IsInMainFrame()) {
// Block top-level navigations to blob: or filesystem: URLs with extension
// origin from non-extension processes. See https://crbug.com/645028.
bool current_frame_is_extension_process =
!!registry->enabled_extensions().GetExtensionOrAppByURL(
navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
if (!url_has_extension_scheme && !current_frame_is_extension_process) {
// Relax this restriction for navigations that will result in downloads.
// See https://crbug.com/714373.
if (target_origin.scheme() == kExtensionScheme &&
navigation_handle()->GetSuggestedFilename().has_value()) {
return content::NavigationThrottle::PROCEED;
}
// Relax this restriction for apps that use <webview>. See
// https://crbug.com/652077.
bool has_webview_permission =
target_extension->permissions_data()->HasAPIPermission(
APIPermission::kWebView);
if (!has_webview_permission)
return content::NavigationThrottle::CANCEL;
// Block all navigations to blob: or filesystem: URLs with extension
// origin from non-extension processes. See https://crbug.com/645028 and
// https://crbug.com/836858.
bool current_frame_is_extension_process =
!!registry->enabled_extensions().GetExtensionOrAppByURL(
navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
if (!url_has_extension_scheme && !current_frame_is_extension_process) {
// Relax this restriction for navigations that will result in downloads.
// See https://crbug.com/714373.
if (target_origin.scheme() == kExtensionScheme &&
navigation_handle()->GetSuggestedFilename().has_value()) {
return content::NavigationThrottle::PROCEED;
}
// Relax this restriction for apps that use <webview>. See
// https://crbug.com/652077.
bool has_webview_permission =
target_extension->permissions_data()->HasAPIPermission(
APIPermission::kWebView);
if (!has_webview_permission)
return content::NavigationThrottle::CANCEL;
}
if (navigation_handle()->IsInMainFrame()) {
guest_view::GuestViewBase* guest =
guest_view::GuestViewBase::FromWebContents(web_contents);
if (url_has_extension_scheme && guest) {
......
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