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

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: Address comments 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 const int kRequestIdNotPreviouslyUsed = 10000;
mmenke 2016/01/28 21:12:33 nit: Should have a comment about this.
gzobqq 2016/01/30 07:18:57 Done.
50
47 // This is a helper function for the tests which attempt to create a 51 // This is a helper function for the tests which attempt to create a
48 // duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects 52 // duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
49 // with the same process and routing ids, which causes a collision. 53 // 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 54 // 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 55 // 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 56 // 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 57 // 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 58 // into |target_routing_id| and the pending RenderViewHost which is used for
55 // the attempt is the return value. 59 // the attempt is the return value.
56 RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell, 60 RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 else 95 else
92 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host(); 96 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host();
93 97
94 EXPECT_TRUE(next_rfh); 98 EXPECT_TRUE(next_rfh);
95 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(), 99 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(),
96 next_rfh->GetProcess()->GetID()); 100 next_rfh->GetProcess()->GetID());
97 101
98 return next_rfh->render_view_host(); 102 return next_rfh->render_view_host();
99 } 103 }
100 104
101 ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) { 105 ResourceHostMsg_Request CreateXHRRequest(const char* url) {
102 ResourceHostMsg_Request request; 106 ResourceHostMsg_Request request;
103 request.method = "GET"; 107 request.method = "GET";
104 request.url = GURL("http://bar.com/simple_page.html"); 108 request.url = GURL(url);
105 request.first_party_for_cookies = GURL(origin);
106 request.referrer_policy = blink::WebReferrerPolicyDefault; 109 request.referrer_policy = blink::WebReferrerPolicyDefault;
107 request.headers = base::StringPrintf("Origin: %s\r\n", origin);
108 request.load_flags = 0; 110 request.load_flags = 0;
109 request.origin_pid = 0; 111 request.origin_pid = 0;
110 request.resource_type = RESOURCE_TYPE_XHR; 112 request.resource_type = RESOURCE_TYPE_XHR;
111 request.request_context = 0; 113 request.request_context = 0;
112 request.appcache_host_id = kAppCacheNoHostId; 114 request.appcache_host_id = kAppCacheNoHostId;
113 request.download_to_file = false; 115 request.download_to_file = false;
114 request.should_reset_appcache = false; 116 request.should_reset_appcache = false;
115 request.is_main_frame = true; 117 request.is_main_frame = true;
116 request.parent_is_main_frame = false; 118 request.parent_is_main_frame = false;
117 request.parent_render_frame_id = -1; 119 request.parent_render_frame_id = -1;
118 request.transition_type = ui::PAGE_TRANSITION_LINK; 120 request.transition_type = ui::PAGE_TRANSITION_LINK;
119 request.allow_download = true; 121 request.allow_download = true;
120 return request; 122 return request;
121 } 123 }
122 124
125 ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
126 ResourceHostMsg_Request request = CreateXHRRequest("http://bar.com/simple_page .html");
mmenke 2016/01/28 21:12:33 nit: Split onto two lines, so no line is over 80
Charlie Reis 2016/01/28 22:05:16 Tip: Running "git cl format" should take care of t
gzobqq 2016/01/30 07:18:57 Done.
gzobqq 2016/01/30 07:18:57 That helps, thanks.
127 request.first_party_for_cookies = GURL(origin);
128 request.headers = base::StringPrintf("Origin: %s\r\n", origin);
129 return request;
130 }
131
132 void TryCreateDuplicateRequestIds(Shell *shell, bool block_loaders) {
133 NavigateToURL(shell, GURL("http://foo.com/simple_page.html"));
134 RenderFrameHost* web_rfh = shell->web_contents()->GetMainFrame();
Charlie Reis 2016/01/28 22:05:16 nit: s/web_rfh/rfh/ (The web_ prefix was useful i
gzobqq 2016/01/30 07:18:57 Done.
135
136 if (block_loaders) {
137 // Test the case where loaders are placed into blocked_loaders_map_.
138 int child_id = web_rfh->GetProcess()->GetID();
139 BrowserThread::PostTask(
140 BrowserThread::IO, FROM_HERE,
141 base::Bind(&ResourceDispatcherHost::BlockRequestsForRoute,
142 base::Unretained(ResourceDispatcherHost::Get()),
143 child_id, web_rfh->GetRoutingID()));
144 }
145
146 // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl
147 // to finish all pending requests. It is never sent, so the following URL
148 // blocks indefinitely, which is good because the request stays alive and the
149 // test can try to reuse the request id without a race.
150 const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl;
151 ResourceHostMsg_Request request(CreateXHRRequest(blocking_url));
152
153 RenderProcessHostWatcher web_process_killed(
154 web_rfh->GetProcess(),
155 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
156 // Use the same request id twice.
Charlie Reis 2016/01/28 22:05:16 nit: Move comment above the RenderProcessHostWatch
gzobqq 2016/01/30 07:18:58 Done.
157 IPC::IpcSecurityTestUtil::PwnMessageReceived(
158 web_rfh->GetProcess()->GetChannel(),
159 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
160 kRequestIdNotPreviouslyUsed, request));
161 IPC::IpcSecurityTestUtil::PwnMessageReceived(
162 web_rfh->GetProcess()->GetChannel(),
163 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
164 kRequestIdNotPreviouslyUsed, request));
165 web_process_killed.Wait();
166 }
167
123 } // namespace 168 } // namespace
124 169
125 170
126 // The goal of these tests will be to "simulate" exploited renderer processes, 171 // The goal of these tests will be to "simulate" exploited renderer processes,
127 // which can send arbitrary IPC messages and confuse browser process internal 172 // 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 173 // state, leading to security bugs. We are trying to verify that the browser
129 // doesn't perform any dangerous operations in such cases. 174 // doesn't perform any dangerous operations in such cases.
130 class SecurityExploitBrowserTest : public ContentBrowserTest { 175 class SecurityExploitBrowserTest : public ContentBrowserTest {
131 public: 176 public:
132 SecurityExploitBrowserTest() {} 177 SecurityExploitBrowserTest() {}
133 178
134 void SetUpCommandLine(base::CommandLine* command_line) override { 179 void SetUpCommandLine(base::CommandLine* command_line) override {
135 ASSERT_TRUE(embedded_test_server()->Start()); 180 ASSERT_TRUE(embedded_test_server()->Start());
136 181
137 // Add a host resolver rule to map all outgoing requests to the test server. 182 // 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 183 // This allows us to use "real" hostnames in URLs, which we can use to
139 // create arbitrary SiteInstances. 184 // create arbitrary SiteInstances.
140 command_line->AppendSwitchASCII( 185 command_line->AppendSwitchASCII(
141 switches::kHostResolverRules, 186 switches::kHostResolverRules,
142 "MAP * " + 187 "MAP * " +
143 net::HostPortPair::FromURL(embedded_test_server()->base_url()) 188 net::HostPortPair::FromURL(embedded_test_server()->base_url())
144 .ToString() + 189 .ToString() +
145 ",EXCLUDE localhost"); 190 ",EXCLUDE localhost");
146 } 191 }
147 192
193 void SetUpOnMainThread() override {
194 BrowserThread::PostTask(
195 BrowserThread::IO, FROM_HERE,
196 base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
197 }
198
148 protected: 199 protected:
149 // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will 200 // Tests that a given file path sent in a ViewHostMsg_RunFileChooser will
150 // cause renderer to be killed. 201 // cause renderer to be killed.
151 void TestFileChooserWithPath(const base::FilePath& path); 202 void TestFileChooserWithPath(const base::FilePath& path);
152 }; 203 };
153 204
154 void SecurityExploitBrowserTest::TestFileChooserWithPath( 205 void SecurityExploitBrowserTest::TestFileChooserWithPath(
155 const base::FilePath& path) { 206 const base::FilePath& path) {
156 GURL foo("http://foo.com/simple_page.html"); 207 GURL foo("http://foo.com/simple_page.html");
157 NavigateToURL(shell(), foo); 208 NavigateToURL(shell(), foo);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 NavigateToURL(shell(), web_url); 428 NavigateToURL(shell(), web_url);
378 RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame(); 429 RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame();
379 430
380 // Web processes cannot make XHRs with chrome:// Origin headers. 431 // Web processes cannot make XHRs with chrome:// Origin headers.
381 { 432 {
382 RenderProcessHostWatcher web_process_killed( 433 RenderProcessHostWatcher web_process_killed(
383 web_rfh->GetProcess(), 434 web_rfh->GetProcess(),
384 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 435 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
385 IPC::IpcSecurityTestUtil::PwnMessageReceived( 436 IPC::IpcSecurityTestUtil::PwnMessageReceived(
386 web_rfh->GetProcess()->GetChannel(), 437 web_rfh->GetProcess()->GetChannel(),
387 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 438 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
439 kRequestIdNotPreviouslyUsed,
388 chrome_origin_msg)); 440 chrome_origin_msg));
389 web_process_killed.Wait(); 441 web_process_killed.Wait();
390 } 442 }
391 443
392 // Web processes cannot make XHRs with URLs that the content embedder expects 444 // Web processes cannot make XHRs with URLs that the content embedder expects
393 // to have process isolation. Ideally this would test chrome-extension:// 445 // 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 446 // 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/. 447 // ResourceHostMsg_Request IPC can't be created in a test outside content/.
396 NavigateToURL(shell(), web_url); 448 NavigateToURL(shell(), web_url);
397 { 449 {
398 // Set up a ContentBrowserClient that simulates an app URL in a non-app 450 // Set up a ContentBrowserClient that simulates an app URL in a non-app
399 // process. 451 // process.
400 IsolatedAppContentBrowserClient app_client; 452 IsolatedAppContentBrowserClient app_client;
401 ContentBrowserClient* old_client = SetBrowserClientForTesting(&app_client); 453 ContentBrowserClient* old_client = SetBrowserClientForTesting(&app_client);
402 RenderProcessHostWatcher web_process_killed( 454 RenderProcessHostWatcher web_process_killed(
403 web_rfh->GetProcess(), 455 web_rfh->GetProcess(),
404 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 456 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
405 IPC::IpcSecurityTestUtil::PwnMessageReceived( 457 IPC::IpcSecurityTestUtil::PwnMessageReceived(
406 web_rfh->GetProcess()->GetChannel(), 458 web_rfh->GetProcess()->GetChannel(),
407 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 459 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
460 kRequestIdNotPreviouslyUsed,
408 embedder_isolated_origin_msg)); 461 embedder_isolated_origin_msg));
409 web_process_killed.Wait(); 462 web_process_killed.Wait();
410 SetBrowserClientForTesting(old_client); 463 SetBrowserClientForTesting(old_client);
411 } 464 }
412 465
413 // Web processes cannot make XHRs with invalid Origin headers. 466 // Web processes cannot make XHRs with invalid Origin headers.
414 NavigateToURL(shell(), web_url); 467 NavigateToURL(shell(), web_url);
415 { 468 {
416 RenderProcessHostWatcher web_process_killed( 469 RenderProcessHostWatcher web_process_killed(
417 web_rfh->GetProcess(), 470 web_rfh->GetProcess(),
418 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 471 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
419 IPC::IpcSecurityTestUtil::PwnMessageReceived( 472 IPC::IpcSecurityTestUtil::PwnMessageReceived(
420 web_rfh->GetProcess()->GetChannel(), 473 web_rfh->GetProcess()->GetChannel(),
421 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 474 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
475 kRequestIdNotPreviouslyUsed,
422 invalid_origin_msg)); 476 invalid_origin_msg));
423 web_process_killed.Wait(); 477 web_process_killed.Wait();
424 } 478 }
425 479
426 // Web processes cannot make XHRs with invalid scheme Origin headers. 480 // Web processes cannot make XHRs with invalid scheme Origin headers.
427 NavigateToURL(shell(), web_url); 481 NavigateToURL(shell(), web_url);
428 { 482 {
429 RenderProcessHostWatcher web_process_killed( 483 RenderProcessHostWatcher web_process_killed(
430 web_rfh->GetProcess(), 484 web_rfh->GetProcess(),
431 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 485 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
432 IPC::IpcSecurityTestUtil::PwnMessageReceived( 486 IPC::IpcSecurityTestUtil::PwnMessageReceived(
433 web_rfh->GetProcess()->GetChannel(), 487 web_rfh->GetProcess()->GetChannel(),
434 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1, 488 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
489 kRequestIdNotPreviouslyUsed,
435 invalid_scheme_origin_msg)); 490 invalid_scheme_origin_msg));
436 web_process_killed.Wait(); 491 web_process_killed.Wait();
437 } 492 }
438 } 493 }
439 494
495 // Renderer process should not be able to create multiple requests with the same
496 // id.
497 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
498 // Existing loader in pending_loaders_.
499 TryCreateDuplicateRequestIds(shell(), false);
500 // Existing loader in blocked_loaders_map_.
501 TryCreateDuplicateRequestIds(shell(), true);
502 }
503
440 } // namespace content 504 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698