diff options
author | gzobqq <gzobqq@gmail.com> | 2016-01-30 05:07:06 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-30 13:08:02 +0000 |
commit | 1af4fada49c4f3890f16daac31d38379a9d782b2 (patch) | |
tree | d559d12b309ccff079472769d1cc6472fbf0bce3 /content/browser/security_exploit_browsertest.cc | |
parent | f5d1a9c599c7cd6833455eacb4ec694a47c1f1b0 (diff) | |
download | chromium_src-1af4fada49c4f3890f16daac31d38379a9d782b2.zip chromium_src-1af4fada49c4f3890f16daac31d38379a9d782b2.tar.gz chromium_src-1af4fada49c4f3890f16daac31d38379a9d782b2.tar.bz2 |
Block a compromised renderer from reusing request ids.
BUG=578882
Review URL: https://codereview.chromium.org/1608573002
Cr-Commit-Position: refs/heads/master@{#372547}
Diffstat (limited to 'content/browser/security_exploit_browsertest.cc')
-rw-r--r-- | content/browser/security_exploit_browsertest.cc | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index c515609..6714e9a 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc @@ -23,6 +23,7 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/interstitial_page_delegate.h" +#include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/appcache_info.h" #include "content/public/common/browser_side_navigation_policy.h" @@ -37,6 +38,7 @@ #include "ipc/ipc_security_test_util.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/url_request/url_request_slow_download_job.h" using IPC::IpcSecurityTestUtil; @@ -44,6 +46,11 @@ namespace content { namespace { +// This request id is used by tests that craft a +// ResourceHostMsg_RequestResource. The id is sufficiently large that it doesn't +// collide with ids used by previous navigation requests. +const int kRequestIdNotPreviouslyUsed = 10000; + // This is a helper function for the tests which attempt to create a // duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects // with the same process and routing ids, which causes a collision. @@ -98,13 +105,11 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, return next_rfh->render_view_host(); } -ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { +ResourceHostMsg_Request CreateXHRRequest(const char* url) { ResourceHostMsg_Request request; request.method = "GET"; - request.url = GURL("http://bar.com/simple_page.html"); - request.first_party_for_cookies = GURL(origin); + request.url = GURL(url); request.referrer_policy = blink::WebReferrerPolicyDefault; - request.headers = base::StringPrintf("Origin: %s\r\n", origin); request.load_flags = 0; request.origin_pid = 0; request.resource_type = RESOURCE_TYPE_XHR; @@ -120,6 +125,49 @@ ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { return request; } +ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { + ResourceHostMsg_Request request = + CreateXHRRequest("http://bar.com/simple_page.html"); + request.first_party_for_cookies = GURL(origin); + request.headers = base::StringPrintf("Origin: %s\r\n", origin); + return request; +} + +void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) { + NavigateToURL(shell, GURL("http://foo.com/simple_page.html")); + RenderFrameHost* rfh = shell->web_contents()->GetMainFrame(); + + if (block_loaders) { + // Test the case where loaders are placed into blocked_loaders_map_. + int child_id = rfh->GetProcess()->GetID(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ResourceDispatcherHost::BlockRequestsForRoute, + base::Unretained(ResourceDispatcherHost::Get()), child_id, + rfh->GetRoutingID())); + } + + // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl + // to finish all pending requests. It is never sent, so the following URL + // blocks indefinitely, which is good because the request stays alive and the + // test can try to reuse the request id without a race. + const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl; + ResourceHostMsg_Request request(CreateXHRRequest(blocking_url)); + + // Use the same request id twice. + RenderProcessHostWatcher process_killed( + rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + IPC::IpcSecurityTestUtil::PwnMessageReceived( + rfh->GetProcess()->GetChannel(), + ResourceHostMsg_RequestResource(rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, request)); + IPC::IpcSecurityTestUtil::PwnMessageReceived( + rfh->GetProcess()->GetChannel(), + ResourceHostMsg_RequestResource(rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, request)); + process_killed.Wait(); +} + } // namespace @@ -145,6 +193,12 @@ class SecurityExploitBrowserTest : public ContentBrowserTest { ",EXCLUDE localhost"); } + void SetUpOnMainThread() override { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); + } + protected: // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will // cause renderer to be killed. @@ -384,7 +438,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); IPC::IpcSecurityTestUtil::PwnMessageReceived( web_rfh->GetProcess()->GetChannel(), - ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, + ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, chrome_origin_msg)); web_process_killed.Wait(); } @@ -404,7 +459,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); IPC::IpcSecurityTestUtil::PwnMessageReceived( web_rfh->GetProcess()->GetChannel(), - ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, + ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, embedder_isolated_origin_msg)); web_process_killed.Wait(); SetBrowserClientForTesting(old_client); @@ -418,7 +474,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); IPC::IpcSecurityTestUtil::PwnMessageReceived( web_rfh->GetProcess()->GetChannel(), - ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, + ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, invalid_origin_msg)); web_process_killed.Wait(); } @@ -431,10 +488,20 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) { RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); IPC::IpcSecurityTestUtil::PwnMessageReceived( web_rfh->GetProcess()->GetChannel(), - ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, + ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), + kRequestIdNotPreviouslyUsed, invalid_scheme_origin_msg)); web_process_killed.Wait(); } } +// Renderer process should not be able to create multiple requests with the same +// id. +IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) { + // Existing loader in pending_loaders_. + TryCreateDuplicateRequestIds(shell(), false); + // Existing loader in blocked_loaders_map_. + TryCreateDuplicateRequestIds(shell(), true); +} + } // namespace content |