Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: content/browser/security_exploit_browsertest.cc

Issue 1608573002: RDH: Block a compromised renderer from reusing request ids (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/containers/hash_tables.h" 8 #include "base/containers/hash_tables.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "build/build_config.h" 11 #include "build/build_config.h"
12 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" 12 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
13 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 13 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
14 #include "content/browser/frame_host/navigator.h" 14 #include "content/browser/frame_host/navigator.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h" 15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/renderer_host/render_view_host_factory.h" 16 #include "content/browser/renderer_host/render_view_host_factory.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h" 17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/web_contents/web_contents_impl.h" 18 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/common/frame_messages.h" 19 #include "content/common/frame_messages.h"
20 #include "content/common/resource_messages.h" 20 #include "content/common/resource_messages.h"
21 #include "content/common/view_messages.h" 21 #include "content/common/view_messages.h"
22 #include "content/public/browser/browser_context.h" 22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/content_browser_client.h" 23 #include "content/public/browser/content_browser_client.h"
24 #include "content/public/browser/interstitial_page.h" 24 #include "content/public/browser/interstitial_page.h"
25 #include "content/public/browser/interstitial_page_delegate.h" 25 #include "content/public/browser/interstitial_page_delegate.h"
26 #include "content/public/browser/resource_dispatcher_host.h"
26 #include "content/public/browser/storage_partition.h" 27 #include "content/public/browser/storage_partition.h"
27 #include "content/public/common/appcache_info.h" 28 #include "content/public/common/appcache_info.h"
28 #include "content/public/common/browser_side_navigation_policy.h" 29 #include "content/public/common/browser_side_navigation_policy.h"
29 #include "content/public/common/content_switches.h" 30 #include "content/public/common/content_switches.h"
30 #include "content/public/common/file_chooser_params.h" 31 #include "content/public/common/file_chooser_params.h"
31 #include "content/public/test/browser_test_utils.h" 32 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/content_browser_test.h" 33 #include "content/public/test/content_browser_test.h"
33 #include "content/public/test/content_browser_test_utils.h" 34 #include "content/public/test/content_browser_test_utils.h"
34 #include "content/public/test/test_utils.h" 35 #include "content/public/test/test_utils.h"
35 #include "content/shell/browser/shell.h" 36 #include "content/shell/browser/shell.h"
36 #include "content/test/test_content_browser_client.h" 37 #include "content/test/test_content_browser_client.h"
37 #include "ipc/ipc_security_test_util.h" 38 #include "ipc/ipc_security_test_util.h"
38 #include "net/dns/mock_host_resolver.h" 39 #include "net/dns/mock_host_resolver.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h" 40 #include "net/test/embedded_test_server/embedded_test_server.h"
41 #include "net/test/url_request/url_request_slow_download_job.h"
40 42
41 using IPC::IpcSecurityTestUtil; 43 using IPC::IpcSecurityTestUtil;
42 44
43 namespace content { 45 namespace content {
44 46
45 namespace { 47 namespace {
46 48
49 // This request id is used by tests that craft a
50 // ResourceHostMsg_RequestResource. The id is sufficiently large that it doesn't
51 // collide with ids used by previous navigation requests.
52 const int kRequestIdNotPreviouslyUsed = 10000;
53
47 // This is a helper function for the tests which attempt to create a 54 // This is a helper function for the tests which attempt to create a
48 // duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects 55 // duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
49 // with the same process and routing ids, which causes a collision. 56 // with the same process and routing ids, which causes a collision.
50 // It creates a couple of windows in process 1, which causes a few routing ids 57 // It creates a couple of windows in process 1, which causes a few routing ids
51 // to be allocated. Then a cross-process navigation is initiated, which causes a 58 // to be allocated. Then a cross-process navigation is initiated, which causes a
52 // new process 2 to be created and have a pending RenderViewHost for it. The 59 // new process 2 to be created and have a pending RenderViewHost for it. The
53 // routing id of the RenderViewHost which is target for a duplicate is set 60 // routing id of the RenderViewHost which is target for a duplicate is set
54 // into |target_routing_id| and the pending RenderViewHost which is used for 61 // into |target_routing_id| and the pending RenderViewHost which is used for
55 // the attempt is the return value. 62 // the attempt is the return value.
56 RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, 63 RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 else 98 else
92 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host(); 99 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host();
93 100
94 EXPECT_TRUE(next_rfh); 101 EXPECT_TRUE(next_rfh);
95 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(), 102 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(),
96 next_rfh->GetProcess()->GetID()); 103 next_rfh->GetProcess()->GetID());
97 104
98 return next_rfh->render_view_host(); 105 return next_rfh->render_view_host();
99 } 106 }
100 107
101 ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { 108 ResourceHostMsg_Request CreateXHRRequest(const char* url) {
102 ResourceHostMsg_Request request; 109 ResourceHostMsg_Request request;
103 request.method = "GET"; 110 request.method = "GET";
104 request.url = GURL("http://bar.com/simple_page.html"); 111 request.url = GURL(url);
105 request.first_party_for_cookies = GURL(origin);
106 request.referrer_policy = blink::WebReferrerPolicyDefault; 112 request.referrer_policy = blink::WebReferrerPolicyDefault;
107 request.headers = base::StringPrintf("Origin: %s\r\n", origin);
108 request.load_flags = 0; 113 request.load_flags = 0;
109 request.origin_pid = 0; 114 request.origin_pid = 0;
110 request.resource_type = RESOURCE_TYPE_XHR; 115 request.resource_type = RESOURCE_TYPE_XHR;
111 request.request_context = 0; 116 request.request_context = 0;
112 request.appcache_host_id = kAppCacheNoHostId; 117 request.appcache_host_id = kAppCacheNoHostId;
113 request.download_to_file = false; 118 request.download_to_file = false;
114 request.should_reset_appcache = false; 119 request.should_reset_appcache = false;
115 request.is_main_frame = true; 120 request.is_main_frame = true;
116 request.parent_is_main_frame = false; 121 request.parent_is_main_frame = false;
117 request.parent_render_frame_id = -1; 122 request.parent_render_frame_id = -1;
118 request.transition_type = ui::PAGE_TRANSITION_LINK; 123 request.transition_type = ui::PAGE_TRANSITION_LINK;
119 request.allow_download = true; 124 request.allow_download = true;
120 return request; 125 return request;
121 } 126 }
122 127
128 ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
129 ResourceHostMsg_Request request =
130 CreateXHRRequest("http://bar.com/simple_page.html");
131 request.first_party_for_cookies = GURL(origin);
132 request.headers = base::StringPrintf("Origin: %s\r\n", origin);
133 return request;
134 }
135
136 void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
137 NavigateToURL(shell, GURL("http://foo.com/simple_page.html"));
138 RenderFrameHost* rfh = shell->web_contents()->GetMainFrame();
139
140 if (block_loaders) {
141 // Test the case where loaders are placed into blocked_loaders_map_.
142 int child_id = rfh->GetProcess()->GetID();
143 BrowserThread::PostTask(
144 BrowserThread::IO, FROM_HERE,
145 base::Bind(&ResourceDispatcherHost::BlockRequestsForRoute,
146 base::Unretained(ResourceDispatcherHost::Get()), child_id,
147 rfh->GetRoutingID()));
148 }
149
150 // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl
151 // to finish all pending requests. It is never sent, so the following URL
152 // blocks indefinitely, which is good because the request stays alive and the
153 // test can try to reuse the request id without a race.
154 const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl;
155 ResourceHostMsg_Request request(CreateXHRRequest(blocking_url));
156
157 // Use the same request id twice.
158 RenderProcessHostWatcher process_killed(
159 rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
160 IPC::IpcSecurityTestUtil::PwnMessageReceived(
161 rfh->GetProcess()->GetChannel(),
162 ResourceHostMsg_RequestResource(rfh->GetRoutingID(),
163 kRequestIdNotPreviouslyUsed, request));
164 IPC::IpcSecurityTestUtil::PwnMessageReceived(
165 rfh->GetProcess()->GetChannel(),
166 ResourceHostMsg_RequestResource(rfh->GetRoutingID(),
167 kRequestIdNotPreviouslyUsed, request));
168 process_killed.Wait();
169 }
170
123 } // namespace 171 } // namespace
124 172
125 173
126 // The goal of these tests will be to "simulate" exploited renderer processes, 174 // The goal of these tests will be to "simulate" exploited renderer processes,
127 // which can send arbitrary IPC messages and confuse browser process internal 175 // which can send arbitrary IPC messages and confuse browser process internal
128 // state, leading to security bugs. We are trying to verify that the browser 176 // state, leading to security bugs. We are trying to verify that the browser
129 // doesn't perform any dangerous operations in such cases. 177 // doesn't perform any dangerous operations in such cases.
130 class SecurityExploitBrowserTest : public ContentBrowserTest { 178 class SecurityExploitBrowserTest : public ContentBrowserTest {
131 public: 179 public:
132 SecurityExploitBrowserTest() {} 180 SecurityExploitBrowserTest() {}
133 181
134 void SetUpCommandLine(base::CommandLine* command_line) override { 182 void SetUpCommandLine(base::CommandLine* command_line) override {
135 ASSERT_TRUE(embedded_test_server()->Start()); 183 ASSERT_TRUE(embedded_test_server()->Start());
136 184
137 // Add a host resolver rule to map all outgoing requests to the test server. 185 // Add a host resolver rule to map all outgoing requests to the test server.
138 // This allows us to use "real" hostnames in URLs, which we can use to 186 // This allows us to use "real" hostnames in URLs, which we can use to
139 // create arbitrary SiteInstances. 187 // create arbitrary SiteInstances.
140 command_line->AppendSwitchASCII( 188 command_line->AppendSwitchASCII(
141 switches::kHostResolverRules, 189 switches::kHostResolverRules,
142 "MAP * " + 190 "MAP * " +
143 net::HostPortPair::FromURL(embedded_test_server()->base_url()) 191 net::HostPortPair::FromURL(embedded_test_server()->base_url())
144 .ToString() + 192 .ToString() +
145 ",EXCLUDE localhost"); 193 ",EXCLUDE localhost");
146 } 194 }
147 195
196 void SetUpOnMainThread() override {
197 BrowserThread::PostTask(
198 BrowserThread::IO, FROM_HERE,
199 base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
200 }
201
148 protected: 202 protected:
149 // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will 203 // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will
150 // cause renderer to be killed. 204 // cause renderer to be killed.
151 void TestFileChooserWithPath(const base::FilePath& path); 205 void TestFileChooserWithPath(const base::FilePath& path);
152 }; 206 };
153 207
154 void SecurityExploitBrowserTest::TestFileChooserWithPath( 208 void SecurityExploitBrowserTest::TestFileChooserWithPath(
155 const base::FilePath& path) { 209 const base::FilePath& path) {
156 GURL foo("http://foo.com/simple_page.html"); 210 GURL foo("http://foo.com/simple_page.html");
157 NavigateToURL(shell(), foo); 211 NavigateToURL(shell(), foo);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 NavigateToURL(shell(), web_url); 431 NavigateToURL(shell(), web_url);
378 RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame(); 432 RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame();
379 433
380 // Web processes cannot make XHRs with chrome:// Origin headers. 434 // Web processes cannot make XHRs with chrome:// Origin headers.
381 { 435 {
382 RenderProcessHostWatcher web_process_killed( 436 RenderProcessHostWatcher web_process_killed(
383 web_rfh->GetProcess(), 437 web_rfh->GetProcess(),
384 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 438 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
385 IPC::IpcSecurityTestUtil::PwnMessageReceived( 439 IPC::IpcSecurityTestUtil::PwnMessageReceived(
386 web_rfh->GetProcess()->GetChannel(), 440 web_rfh->GetProcess()->GetChannel(),
387 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 441 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
442 kRequestIdNotPreviouslyUsed,
388 chrome_origin_msg)); 443 chrome_origin_msg));
389 web_process_killed.Wait(); 444 web_process_killed.Wait();
390 } 445 }
391 446
392 // Web processes cannot make XHRs with URLs that the content embedder expects 447 // Web processes cannot make XHRs with URLs that the content embedder expects
393 // to have process isolation. Ideally this would test chrome-extension:// 448 // to have process isolation. Ideally this would test chrome-extension://
394 // URLs for Chrome Apps, but those can't be tested inside content/ and the 449 // URLs for Chrome Apps, but those can't be tested inside content/ and the
395 // ResourceHostMsg_Request IPC can't be created in a test outside content/. 450 // ResourceHostMsg_Request IPC can't be created in a test outside content/.
396 NavigateToURL(shell(), web_url); 451 NavigateToURL(shell(), web_url);
397 { 452 {
398 // Set up a ContentBrowserClient that simulates an app URL in a non-app 453 // Set up a ContentBrowserClient that simulates an app URL in a non-app
399 // process. 454 // process.
400 IsolatedAppContentBrowserClient app_client; 455 IsolatedAppContentBrowserClient app_client;
401 ContentBrowserClient* old_client = SetBrowserClientForTesting(&app_client); 456 ContentBrowserClient* old_client = SetBrowserClientForTesting(&app_client);
402 RenderProcessHostWatcher web_process_killed( 457 RenderProcessHostWatcher web_process_killed(
403 web_rfh->GetProcess(), 458 web_rfh->GetProcess(),
404 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 459 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
405 IPC::IpcSecurityTestUtil::PwnMessageReceived( 460 IPC::IpcSecurityTestUtil::PwnMessageReceived(
406 web_rfh->GetProcess()->GetChannel(), 461 web_rfh->GetProcess()->GetChannel(),
407 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 462 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
463 kRequestIdNotPreviouslyUsed,
408 embedder_isolated_origin_msg)); 464 embedder_isolated_origin_msg));
409 web_process_killed.Wait(); 465 web_process_killed.Wait();
410 SetBrowserClientForTesting(old_client); 466 SetBrowserClientForTesting(old_client);
411 } 467 }
412 468
413 // Web processes cannot make XHRs with invalid Origin headers. 469 // Web processes cannot make XHRs with invalid Origin headers.
414 NavigateToURL(shell(), web_url); 470 NavigateToURL(shell(), web_url);
415 { 471 {
416 RenderProcessHostWatcher web_process_killed( 472 RenderProcessHostWatcher web_process_killed(
417 web_rfh->GetProcess(), 473 web_rfh->GetProcess(),
418 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 474 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
419 IPC::IpcSecurityTestUtil::PwnMessageReceived( 475 IPC::IpcSecurityTestUtil::PwnMessageReceived(
420 web_rfh->GetProcess()->GetChannel(), 476 web_rfh->GetProcess()->GetChannel(),
421 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 477 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
478 kRequestIdNotPreviouslyUsed,
422 invalid_origin_msg)); 479 invalid_origin_msg));
423 web_process_killed.Wait(); 480 web_process_killed.Wait();
424 } 481 }
425 482
426 // Web processes cannot make XHRs with invalid scheme Origin headers. 483 // Web processes cannot make XHRs with invalid scheme Origin headers.
427 NavigateToURL(shell(), web_url); 484 NavigateToURL(shell(), web_url);
428 { 485 {
429 RenderProcessHostWatcher web_process_killed( 486 RenderProcessHostWatcher web_process_killed(
430 web_rfh->GetProcess(), 487 web_rfh->GetProcess(),
431 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 488 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
432 IPC::IpcSecurityTestUtil::PwnMessageReceived( 489 IPC::IpcSecurityTestUtil::PwnMessageReceived(
433 web_rfh->GetProcess()->GetChannel(), 490 web_rfh->GetProcess()->GetChannel(),
434 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 491 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
492 kRequestIdNotPreviouslyUsed,
435 invalid_scheme_origin_msg)); 493 invalid_scheme_origin_msg));
436 web_process_killed.Wait(); 494 web_process_killed.Wait();
437 } 495 }
438 } 496 }
439 497
498 // Renderer process should not be able to create multiple requests with the same
499 // id.
500 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
501 // Existing loader in pending_loaders_.
502 TryCreateDuplicateRequestIds(shell(), false);
503 // Existing loader in blocked_loaders_map_.
504 TryCreateDuplicateRequestIds(shell(), true);
505 }
506
440 } // namespace content 507 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_dispatcher_host_impl.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698