Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "content/browser/child_process_security_policy_impl.h" | 14 #include "content/browser/child_process_security_policy_impl.h" |
| 15 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 15 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 16 #include "content/public/browser/navigation_entry.h" | 16 #include "content/public/browser/navigation_entry.h" |
| 17 #include "content/public/browser/navigation_handle.h" | 17 #include "content/public/browser/navigation_handle.h" |
| 18 #include "content/public/browser/render_frame_host.h" | |
| 18 #include "content/public/browser/render_process_host.h" | 19 #include "content/public/browser/render_process_host.h" |
| 19 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 20 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
| 20 #include "content/public/browser/resource_throttle.h" | 21 #include "content/public/browser/resource_throttle.h" |
| 21 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
| 22 #include "content/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
| 23 #include "content/public/test/browser_test_utils.h" | 24 #include "content/public/test/browser_test_utils.h" |
| 24 #include "content/public/test/content_browser_test.h" | 25 #include "content/public/test/content_browser_test.h" |
| 25 #include "content/public/test/content_browser_test_utils.h" | 26 #include "content/public/test/content_browser_test_utils.h" |
| 26 #include "content/public/test/navigation_handle_observer.h" | 27 #include "content/public/test/navigation_handle_observer.h" |
| 27 #include "content/public/test/test_navigation_observer.h" | 28 #include "content/public/test/test_navigation_observer.h" |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 "window.domAutomationController.send(" | 509 "window.domAutomationController.send(" |
| 509 "document.getElementsByTagName('pre')[0].innerText);", | 510 "document.getElementsByTagName('pre')[0].innerText);", |
| 510 &actual_page_body)); | 511 &actual_page_body)); |
| 511 EXPECT_THAT(actual_page_body, ::testing::HasSubstr(file_content)); | 512 EXPECT_THAT(actual_page_body, ::testing::HasSubstr(file_content)); |
| 512 EXPECT_THAT(actual_page_body, | 513 EXPECT_THAT(actual_page_body, |
| 513 ::testing::HasSubstr(file_path.BaseName().AsUTF8Unsafe())); | 514 ::testing::HasSubstr(file_path.BaseName().AsUTF8Unsafe())); |
| 514 EXPECT_THAT(actual_page_body, | 515 EXPECT_THAT(actual_page_body, |
| 515 ::testing::HasSubstr("form-data; name=\"file\"")); | 516 ::testing::HasSubstr("form-data; name=\"file\"")); |
| 516 } | 517 } |
| 517 | 518 |
| 519 // Test that verifies that if navigation originator doesn't have access to a | |
| 520 // file, then no access is granted after a cross-process transfer of POST data. | |
| 521 // | |
| 522 // This test is somewhat similar to | |
| 523 // http/tests/navigation/form-targets-cross-site-frame-post.html layout test | |
| 524 // except that it 1) tests with files, 2) simulates a malicious scenario and 3) | |
| 525 // verifies file acecss (all of these 3 things are not possible with layout | |
|
alexmos
2017/05/25 18:17:33
nit: access
Łukasz Anforowicz
2017/05/25 19:56:01
Done.
| |
| 526 // tests). | |
| 527 // | |
| 528 // This test is very similar to CrossSiteTransferTest.PostWithFileData above, | |
| 529 // except that it simulates a malicious form / POST originator. | |
| 530 IN_PROC_BROWSER_TEST_P(CrossSiteTransferTest, MaliciousPostWithFileData) { | |
| 531 // Navigate to the page with form that posts via 307 redirection to | |
| 532 // |redirect_target_url| (cross-site from |form_url|). Using 307 (rather than | |
| 533 // 302) redirection is important to preserve the HTTP method and POST body. | |
| 534 GURL form_url(embedded_test_server()->GetURL( | |
| 535 "main.com", "/form_that_posts_cross_site.html")); | |
| 536 EXPECT_TRUE(NavigateToURL(shell(), form_url)); | |
| 537 WebContents* form_contents = shell()->web_contents(); | |
| 538 | |
| 539 // Create a new window and make it a target of the form from |form_contents|. | |
| 540 GURL initial_target_url( | |
| 541 embedded_test_server()->GetURL("initial-target.com", "/title1.html")); | |
| 542 WebContentsAddedObserver new_contents_observer; | |
| 543 std::string script = base::StringPrintf( | |
| 544 R"( window.open('%s', 'form-target'); | |
| 545 document.getElementById('file-form').target = 'form-target'; | |
| 546 )", | |
| 547 initial_target_url.spec().c_str()); | |
| 548 EXPECT_TRUE(ExecuteScript(form_contents, script)); | |
| 549 WebContents* target_contents = new_contents_observer.GetWebContents(); | |
| 550 WaitForLoadStop(target_contents); | |
| 551 | |
| 552 // Verify the current location and process placement of |target_contents|. | |
| 553 EXPECT_EQ(initial_target_url, target_contents->GetLastCommittedURL()); | |
| 554 EXPECT_NE(target_contents->GetMainFrame()->GetProcess()->GetID(), | |
| 555 form_contents->GetMainFrame()->GetProcess()->GetID()); | |
| 556 | |
| 557 // Prepare a file to upload. | |
| 558 base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir; | |
| 559 base::ScopedTempDir temp_dir; | |
| 560 base::FilePath file_path; | |
| 561 std::string file_content("test-file-content"); | |
| 562 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
| 563 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &file_path)); | |
| 564 ASSERT_LT( | |
| 565 0, base::WriteFile(file_path, file_content.data(), file_content.size())); | |
| 566 | |
| 567 // Fill out the form to refer to the test file. | |
| 568 std::unique_ptr<FileChooserDelegate> delegate( | |
| 569 new FileChooserDelegate(file_path)); | |
| 570 form_contents->SetDelegate(delegate.get()); | |
| 571 EXPECT_TRUE( | |
| 572 ExecuteScript(form_contents, "document.getElementById('file').click();")); | |
| 573 EXPECT_TRUE(delegate->file_chosen()); | |
| 574 | |
| 575 // Simulate a malicious situation, where the renderer doesn't really have | |
| 576 // access to the file. | |
| 577 ChildProcessSecurityPolicyImpl* security_policy = | |
| 578 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 579 security_policy->RevokeAllPermissionsForFile( | |
| 580 form_contents->GetMainFrame()->GetProcess()->GetID(), file_path); | |
| 581 EXPECT_FALSE(security_policy->CanReadFile( | |
| 582 form_contents->GetMainFrame()->GetProcess()->GetID(), file_path)); | |
| 583 EXPECT_FALSE(security_policy->CanReadFile( | |
| 584 target_contents->GetMainFrame()->GetProcess()->GetID(), file_path)); | |
| 585 | |
| 586 // Submit the form. | |
| 587 RenderProcessHostWatcher process_exit_observer( | |
| 588 form_contents->GetMainFrame()->GetProcess(), | |
| 589 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
| 590 EXPECT_TRUE(ExecuteScript( | |
| 591 form_contents, | |
| 592 "setTimeout(\n" | |
| 593 " function() { document.getElementById('file-form').submit(); },\n" | |
| 594 " 0);")); | |
| 595 process_exit_observer.Wait(); | |
| 596 | |
| 597 // The target frame should still be at the original location - the malicious | |
| 598 // navigation should have been stopped. | |
| 599 EXPECT_EQ(initial_target_url, target_contents->GetLastCommittedURL()); | |
| 600 | |
| 601 // Both processes still shouldn't have access. | |
| 602 EXPECT_FALSE(security_policy->CanReadFile( | |
| 603 form_contents->GetMainFrame()->GetProcess()->GetID(), file_path)); | |
| 604 EXPECT_FALSE(security_policy->CanReadFile( | |
| 605 target_contents->GetMainFrame()->GetProcess()->GetID(), file_path)); | |
| 606 } | |
| 607 | |
| 518 INSTANTIATE_TEST_CASE_P(CrossSiteTransferTest, | 608 INSTANTIATE_TEST_CASE_P(CrossSiteTransferTest, |
| 519 CrossSiteTransferTest, | 609 CrossSiteTransferTest, |
| 520 ::testing::Values(TestParameter::LOADING_WITHOUT_MOJO, | 610 ::testing::Values(TestParameter::LOADING_WITHOUT_MOJO, |
| 521 TestParameter::LOADING_WITH_MOJO)); | 611 TestParameter::LOADING_WITH_MOJO)); |
| 522 | 612 |
| 523 } // namespace content | 613 } // namespace content |
| OLD | NEW |