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

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

Issue 1270663002: Validate the Origin HTTP header in the browser process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update comment Created 5 years, 4 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 "base/command_line.h" 5 #include "base/command_line.h"
6 #include "base/containers/hash_tables.h" 6 #include "base/containers/hash_tables.h"
7 #include "base/strings/utf_string_conversions.h" 7 #include "base/strings/utf_string_conversions.h"
8 #include "content/browser/dom_storage/dom_storage_context_wrapper.h" 8 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
9 #include "content/browser/dom_storage/session_storage_namespace_impl.h" 9 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
10 #include "content/browser/frame_host/navigator.h" 10 #include "content/browser/frame_host/navigator.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h"
11 #include "content/browser/renderer_host/render_view_host_factory.h" 12 #include "content/browser/renderer_host/render_view_host_factory.h"
12 #include "content/browser/renderer_host/render_view_host_impl.h" 13 #include "content/browser/renderer_host/render_view_host_impl.h"
13 #include "content/browser/web_contents/web_contents_impl.h" 14 #include "content/browser/web_contents/web_contents_impl.h"
14 #include "content/common/frame_messages.h" 15 #include "content/common/frame_messages.h"
16 #include "content/common/resource_messages.h"
15 #include "content/common/view_messages.h" 17 #include "content/common/view_messages.h"
16 #include "content/public/browser/browser_context.h" 18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/content_browser_client.h"
17 #include "content/public/browser/interstitial_page.h" 20 #include "content/public/browser/interstitial_page.h"
18 #include "content/public/browser/interstitial_page_delegate.h" 21 #include "content/public/browser/interstitial_page_delegate.h"
19 #include "content/public/browser/storage_partition.h" 22 #include "content/public/browser/storage_partition.h"
23 #include "content/public/common/appcache_info.h"
20 #include "content/public/common/content_switches.h" 24 #include "content/public/common/content_switches.h"
21 #include "content/public/common/file_chooser_params.h" 25 #include "content/public/common/file_chooser_params.h"
22 #include "content/public/test/browser_test_utils.h" 26 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/content_browser_test.h" 27 #include "content/public/test/content_browser_test.h"
24 #include "content/public/test/content_browser_test_utils.h" 28 #include "content/public/test/content_browser_test_utils.h"
25 #include "content/public/test/test_utils.h" 29 #include "content/public/test/test_utils.h"
26 #include "content/shell/browser/shell.h" 30 #include "content/shell/browser/shell.h"
31 #include "content/test/test_content_browser_client.h"
27 #include "ipc/ipc_security_test_util.h" 32 #include "ipc/ipc_security_test_util.h"
28 #include "net/dns/mock_host_resolver.h" 33 #include "net/dns/mock_host_resolver.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h" 34 #include "net/test/embedded_test_server/embedded_test_server.h"
30 35
31 using IPC::IpcSecurityTestUtil; 36 using IPC::IpcSecurityTestUtil;
32 37
33 namespace content { 38 namespace content {
34 39
35 namespace { 40 namespace {
36 41
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host(); 89 next_rfh = wc->GetRenderManagerForTesting()->pending_frame_host();
85 } 90 }
86 91
87 EXPECT_TRUE(next_rfh); 92 EXPECT_TRUE(next_rfh);
88 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(), 93 EXPECT_NE(shell->web_contents()->GetRenderProcessHost()->GetID(),
89 next_rfh->GetProcess()->GetID()); 94 next_rfh->GetProcess()->GetID());
90 95
91 return next_rfh->render_view_host(); 96 return next_rfh->render_view_host();
92 } 97 }
93 98
99 ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
100 ResourceHostMsg_Request request;
101 request.method = "GET";
102 request.url = GURL("http://bar.com/simple_page.html");
103 request.first_party_for_cookies = GURL(origin);
104 request.referrer_policy = blink::WebReferrerPolicyDefault;
105 request.headers = base::StringPrintf("Origin: %s\r\n", origin);
106 request.load_flags = 0;
107 request.origin_pid = 0;
108 request.resource_type = RESOURCE_TYPE_XHR;
109 request.request_context = 0;
110 request.appcache_host_id = kAppCacheNoHostId;
111 request.download_to_file = false;
112 request.should_reset_appcache = false;
113 request.is_main_frame = true;
114 request.parent_is_main_frame = false;
115 request.parent_render_frame_id = -1;
116 request.transition_type = ui::PAGE_TRANSITION_LINK;
117 request.allow_download = true;
118 return request;
119 }
120
94 } // namespace 121 } // namespace
95 122
96 123
97 // The goal of these tests will be to "simulate" exploited renderer processes, 124 // The goal of these tests will be to "simulate" exploited renderer processes,
98 // which can send arbitrary IPC messages and confuse browser process internal 125 // which can send arbitrary IPC messages and confuse browser process internal
99 // state, leading to security bugs. We are trying to verify that the browser 126 // state, leading to security bugs. We are trying to verify that the browser
100 // doesn't perform any dangerous operations in such cases. 127 // doesn't perform any dangerous operations in such cases.
101 class SecurityExploitBrowserTest : public ContentBrowserTest { 128 class SecurityExploitBrowserTest : public ContentBrowserTest {
102 public: 129 public:
103 SecurityExploitBrowserTest() {} 130 SecurityExploitBrowserTest() {}
(...skipping 17 matching lines...) Expand all
121 // cause renderer to be killed. 148 // cause renderer to be killed.
122 void TestFileChooserWithPath(const base::FilePath& path); 149 void TestFileChooserWithPath(const base::FilePath& path);
123 }; 150 };
124 151
125 void SecurityExploitBrowserTest::TestFileChooserWithPath( 152 void SecurityExploitBrowserTest::TestFileChooserWithPath(
126 const base::FilePath& path) { 153 const base::FilePath& path) {
127 GURL foo("http://foo.com/simple_page.html"); 154 GURL foo("http://foo.com/simple_page.html");
128 NavigateToURL(shell(), foo); 155 NavigateToURL(shell(), foo);
129 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle()); 156 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
130 157
131 content::RenderViewHost* compromised_renderer = 158 RenderViewHost* compromised_renderer =
132 shell()->web_contents()->GetRenderViewHost(); 159 shell()->web_contents()->GetRenderViewHost();
133 content::RenderProcessHostWatcher terminated( 160 RenderProcessHostWatcher terminated(
134 shell()->web_contents(), 161 shell()->web_contents(),
135 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 162 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
136 163
137 FileChooserParams params; 164 FileChooserParams params;
138 params.default_file_name = path; 165 params.default_file_name = path;
139 166
140 ViewHostMsg_RunFileChooser evil(compromised_renderer->GetRoutingID(), params); 167 ViewHostMsg_RunFileChooser evil(compromised_renderer->GetRoutingID(), params);
141 168
142 IpcSecurityTestUtil::PwnMessageReceived( 169 IpcSecurityTestUtil::PwnMessageReceived(
143 compromised_renderer->GetProcess()->GetChannel(), evil); 170 compromised_renderer->GetProcess()->GetChannel(), evil);
144 terminated.Wait(); 171 terminated.Wait();
145 } 172 }
146 173
147 // Ensure that we kill the renderer process if we try to give it WebUI 174 // Ensure that we kill the renderer process if we try to give it WebUI
148 // properties and it doesn't have enabled WebUI bindings. 175 // properties and it doesn't have enabled WebUI bindings.
149 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) { 176 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) {
150 GURL foo("http://foo.com/simple_page.html"); 177 GURL foo("http://foo.com/simple_page.html");
151 178
152 NavigateToURL(shell(), foo); 179 NavigateToURL(shell(), foo);
153 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle()); 180 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
154 EXPECT_EQ(0, 181 EXPECT_EQ(0,
155 shell()->web_contents()->GetRenderViewHost()->GetEnabledBindings()); 182 shell()->web_contents()->GetRenderViewHost()->GetEnabledBindings());
156 183
157 content::RenderProcessHostWatcher terminated( 184 RenderProcessHostWatcher terminated(
158 shell()->web_contents(), 185 shell()->web_contents(),
159 content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); 186 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
160 shell()->web_contents()->GetRenderViewHost()->SetWebUIProperty( 187 shell()->web_contents()->GetRenderViewHost()->SetWebUIProperty(
161 "toolkit", "views"); 188 "toolkit", "views");
162 terminated.Wait(); 189 terminated.Wait();
163 } 190 }
164 191
165 // This is a test for crbug.com/312016 attempting to create duplicate 192 // This is a test for crbug.com/312016 attempting to create duplicate
166 // RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves 193 // RenderViewHosts. SetupForDuplicateHosts sets up this test case and leaves
167 // it in a state with pending RenderViewHost. Before the commit of the new 194 // it in a state with pending RenderViewHost. Before the commit of the new
168 // pending RenderViewHost, this test case creates a new window through the new 195 // pending RenderViewHost, this test case creates a new window through the new
169 // process. 196 // process.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 NavigateToURL(shell(), foo); 301 NavigateToURL(shell(), foo);
275 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle()); 302 EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
276 303
277 DOMMessageQueue message_queue; 304 DOMMessageQueue message_queue;
278 305
279 // Install and show an interstitial page. 306 // Install and show an interstitial page.
280 SecurityExploitTestInterstitialPage* interstitial = 307 SecurityExploitTestInterstitialPage* interstitial =
281 new SecurityExploitTestInterstitialPage(shell()->web_contents()); 308 new SecurityExploitTestInterstitialPage(shell()->web_contents());
282 309
283 ASSERT_EQ("", interstitial->last_command()); 310 ASSERT_EQ("", interstitial->last_command());
284 content::WaitForInterstitialAttach(shell()->web_contents()); 311 WaitForInterstitialAttach(shell()->web_contents());
285 312
286 InterstitialPage* interstitial_page = 313 InterstitialPage* interstitial_page =
287 shell()->web_contents()->GetInterstitialPage(); 314 shell()->web_contents()->GetInterstitialPage();
288 ASSERT_TRUE(interstitial_page != NULL); 315 ASSERT_TRUE(interstitial_page != NULL);
289 ASSERT_TRUE(shell()->web_contents()->ShowingInterstitialPage()); 316 ASSERT_TRUE(shell()->web_contents()->ShowingInterstitialPage());
290 ASSERT_TRUE(interstitial_page->GetDelegateForTesting() == interstitial); 317 ASSERT_TRUE(interstitial_page->GetDelegateForTesting() == interstitial);
291 318
292 // The interstitial page ought to be able to send a message. 319 // The interstitial page ought to be able to send a message.
293 std::string message; 320 std::string message;
294 ASSERT_TRUE(message_queue.WaitForMessage(&message)); 321 ASSERT_TRUE(message_queue.WaitForMessage(&message));
295 ASSERT_EQ("\"okay\"", message); 322 ASSERT_EQ("\"okay\"", message);
296 ASSERT_EQ("\"okay\"", interstitial->last_command()); 323 ASSERT_EQ("\"okay\"", interstitial->last_command());
297 324
298 // Send an automation message from the underlying content and wait for it to 325 // Send an automation message from the underlying content and wait for it to
299 // be dispatched on this thread. This message should not be received by the 326 // be dispatched on this thread. This message should not be received by the
300 // interstitial. 327 // interstitial.
301 content::RenderFrameHost* compromised_renderer = 328 RenderFrameHost* compromised_renderer =
302 shell()->web_contents()->GetMainFrame(); 329 shell()->web_contents()->GetMainFrame();
303 FrameHostMsg_DomOperationResponse evil(compromised_renderer->GetRoutingID(), 330 FrameHostMsg_DomOperationResponse evil(compromised_renderer->GetRoutingID(),
304 "evil", MSG_ROUTING_NONE); 331 "evil", MSG_ROUTING_NONE);
305 IpcSecurityTestUtil::PwnMessageReceived( 332 IpcSecurityTestUtil::PwnMessageReceived(
306 compromised_renderer->GetProcess()->GetChannel(), evil); 333 compromised_renderer->GetProcess()->GetChannel(), evil);
307 334
308 ASSERT_TRUE(message_queue.WaitForMessage(&message)); 335 ASSERT_TRUE(message_queue.WaitForMessage(&message));
309 ASSERT_EQ("evil", message) 336 ASSERT_EQ("evil", message)
310 << "Automation message should be received by WebContents."; 337 << "Automation message should be received by WebContents.";
311 ASSERT_EQ("\"okay\"", interstitial->last_command()) 338 ASSERT_EQ("\"okay\"", interstitial->last_command())
312 << "Interstitial should not be affected."; 339 << "Interstitial should not be affected.";
313 340
314 // Send a second message from the interstitial page, and make sure that the 341 // Send a second message from the interstitial page, and make sure that the
315 // "evil" message doesn't arrive in the intervening period. 342 // "evil" message doesn't arrive in the intervening period.
316 ASSERT_TRUE(content::ExecuteScript( 343 ASSERT_TRUE(ExecuteScript(interstitial_page->GetMainFrame(),
317 interstitial_page->GetMainFrame(), 344 "window.domAutomationController.send(\"okay2\");"));
318 "window.domAutomationController.send(\"okay2\");"));
319 ASSERT_TRUE(message_queue.WaitForMessage(&message)); 345 ASSERT_TRUE(message_queue.WaitForMessage(&message));
320 ASSERT_EQ("\"okay2\"", message); 346 ASSERT_EQ("\"okay2\"", message);
321 ASSERT_EQ("\"okay2\"", interstitial->last_command()); 347 ASSERT_EQ("\"okay2\"", interstitial->last_command());
322 } 348 }
323 349
350 class IsolatedAppContentBrowserClient : public TestContentBrowserClient {
351 public:
352 bool IsIllegalOrigin(content::ResourceContext* resource_context,
353 int child_process_id,
354 const GURL& origin) override {
355 // Simulate a case where an app origin is not in an app process.
356 return true;
357 }
358 };
359
360 // Renderer processes should not be able to spoof Origin HTTP headers.
361 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
362 // Create a set of IPC messages with various Origin headers.
363 ResourceHostMsg_Request chrome_origin_msg(
364 CreateXHRRequestWithOrigin("chrome://settings"));
365 ResourceHostMsg_Request embedder_isolated_origin_msg(
366 CreateXHRRequestWithOrigin("https://isolated.bar.com"));
367 ResourceHostMsg_Request invalid_origin_msg(
368 CreateXHRRequestWithOrigin("invalidurl"));
369 ResourceHostMsg_Request invalid_scheme_origin_msg(
370 CreateXHRRequestWithOrigin("fake-scheme://foo"));
371
372 GURL web_url("http://foo.com/simple_page.html");
373 NavigateToURL(shell(), web_url);
374 RenderFrameHost* web_rfh = shell()->web_contents()->GetMainFrame();
375
376 // Web processes cannot make XHRs with chrome:// Origin headers.
377 {
378 RenderProcessHostWatcher web_process_killed(
379 web_rfh->GetProcess(),
380 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
381 IPC::IpcSecurityTestUtil::PwnMessageReceived(
382 web_rfh->GetProcess()->GetChannel(),
383 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
384 chrome_origin_msg));
385 web_process_killed.Wait();
386 }
387
388 // Web processes cannot make XHRs with URLs that the content embedder expects
389 // to have process isolation. Ideally this would test chrome-extension://
390 // URLs for Chrome Apps, but those can't be tested inside content/ and the
391 // ResourceHostMsg_Request IPC can't be created in a test outside content/.
392 NavigateToURL(shell(), web_url);
393 {
394 // Set up a ContentBrowserClient that simulates an app URL in a non-app
395 // process.
396 IsolatedAppContentBrowserClient app_client;
397 ContentBrowserClient* old_client = SetBrowserClientForTesting(&app_client);
398 RenderProcessHostWatcher web_process_killed(
399 web_rfh->GetProcess(),
400 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
401 IPC::IpcSecurityTestUtil::PwnMessageReceived(
402 web_rfh->GetProcess()->GetChannel(),
403 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
404 embedder_isolated_origin_msg));
405 web_process_killed.Wait();
406 SetBrowserClientForTesting(old_client);
407 }
408
409 // Web processes cannot make XHRs with invalid Origin headers.
410 NavigateToURL(shell(), web_url);
411 {
412 RenderProcessHostWatcher web_process_killed(
413 web_rfh->GetProcess(),
414 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
415 IPC::IpcSecurityTestUtil::PwnMessageReceived(
416 web_rfh->GetProcess()->GetChannel(),
417 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
418 invalid_origin_msg));
419 web_process_killed.Wait();
420 }
421
422 // Web processes cannot make XHRs with invalid scheme Origin headers.
423 NavigateToURL(shell(), web_url);
424 {
425 RenderProcessHostWatcher web_process_killed(
426 web_rfh->GetProcess(),
427 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
428 IPC::IpcSecurityTestUtil::PwnMessageReceived(
429 web_rfh->GetProcess()->GetChannel(),
430 ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
431 invalid_scheme_origin_msg));
432 web_process_killed.Wait();
433 }
434 }
435
324 } // namespace content 436 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698