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

Unified Diff: content/browser/cross_site_transfer_browsertest.cc

Issue 2908433003: RenderFrameProxyHost::OnOpenURL needs to validate resource request body. (Closed)
Patch Set: . Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/cross_site_transfer_browsertest.cc
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index 601909e0dc2ac1c70cd7a71f8744f5a47eee6428..192ec2194faf825e3c2e9e14d68062aa37880743 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -15,6 +15,7 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/resource_throttle.h"
@@ -515,6 +516,95 @@ IN_PROC_BROWSER_TEST_P(CrossSiteTransferTest, PostWithFileData) {
::testing::HasSubstr("form-data; name=\"file\""));
}
+// Test that verifies that if navigation originator doesn't have access to a
+// file, then no access is granted after a cross-process transfer of POST data.
+//
+// This test is somewhat similar to
+// http/tests/navigation/form-targets-cross-site-frame-post.html layout test
+// except that it 1) tests with files, 2) simulates a malicious scenario and 3)
+// 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.
+// tests).
+//
+// This test is very similar to CrossSiteTransferTest.PostWithFileData above,
+// except that it simulates a malicious form / POST originator.
+IN_PROC_BROWSER_TEST_P(CrossSiteTransferTest, MaliciousPostWithFileData) {
+ // Navigate to the page with form that posts via 307 redirection to
+ // |redirect_target_url| (cross-site from |form_url|). Using 307 (rather than
+ // 302) redirection is important to preserve the HTTP method and POST body.
+ GURL form_url(embedded_test_server()->GetURL(
+ "main.com", "/form_that_posts_cross_site.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), form_url));
+ WebContents* form_contents = shell()->web_contents();
+
+ // Create a new window and make it a target of the form from |form_contents|.
+ GURL initial_target_url(
+ embedded_test_server()->GetURL("initial-target.com", "/title1.html"));
+ WebContentsAddedObserver new_contents_observer;
+ std::string script = base::StringPrintf(
+ R"( window.open('%s', 'form-target');
+ document.getElementById('file-form').target = 'form-target';
+ )",
+ initial_target_url.spec().c_str());
+ EXPECT_TRUE(ExecuteScript(form_contents, script));
+ WebContents* target_contents = new_contents_observer.GetWebContents();
+ WaitForLoadStop(target_contents);
+
+ // Verify the current location and process placement of |target_contents|.
+ EXPECT_EQ(initial_target_url, target_contents->GetLastCommittedURL());
+ EXPECT_NE(target_contents->GetMainFrame()->GetProcess()->GetID(),
+ form_contents->GetMainFrame()->GetProcess()->GetID());
+
+ // Prepare a file to upload.
+ base::ThreadRestrictions::ScopedAllowIO allow_io_for_temp_dir;
+ base::ScopedTempDir temp_dir;
+ base::FilePath file_path;
+ std::string file_content("test-file-content");
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &file_path));
+ ASSERT_LT(
+ 0, base::WriteFile(file_path, file_content.data(), file_content.size()));
+
+ // Fill out the form to refer to the test file.
+ std::unique_ptr<FileChooserDelegate> delegate(
+ new FileChooserDelegate(file_path));
+ form_contents->SetDelegate(delegate.get());
+ EXPECT_TRUE(
+ ExecuteScript(form_contents, "document.getElementById('file').click();"));
+ EXPECT_TRUE(delegate->file_chosen());
+
+ // Simulate a malicious situation, where the renderer doesn't really have
+ // access to the file.
+ ChildProcessSecurityPolicyImpl* security_policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ security_policy->RevokeAllPermissionsForFile(
+ form_contents->GetMainFrame()->GetProcess()->GetID(), file_path);
+ EXPECT_FALSE(security_policy->CanReadFile(
+ form_contents->GetMainFrame()->GetProcess()->GetID(), file_path));
+ EXPECT_FALSE(security_policy->CanReadFile(
+ target_contents->GetMainFrame()->GetProcess()->GetID(), file_path));
+
+ // Submit the form.
+ RenderProcessHostWatcher process_exit_observer(
+ form_contents->GetMainFrame()->GetProcess(),
+ RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ EXPECT_TRUE(ExecuteScript(
+ form_contents,
+ "setTimeout(\n"
+ " function() { document.getElementById('file-form').submit(); },\n"
+ " 0);"));
+ process_exit_observer.Wait();
+
+ // The target frame should still be at the original location - the malicious
+ // navigation should have been stopped.
+ EXPECT_EQ(initial_target_url, target_contents->GetLastCommittedURL());
+
+ // Both processes still shouldn't have access.
+ EXPECT_FALSE(security_policy->CanReadFile(
+ form_contents->GetMainFrame()->GetProcess()->GetID(), file_path));
+ EXPECT_FALSE(security_policy->CanReadFile(
+ target_contents->GetMainFrame()->GetProcess()->GetID(), file_path));
+}
+
INSTANTIATE_TEST_CASE_P(CrossSiteTransferTest,
CrossSiteTransferTest,
::testing::Values(TestParameter::LOADING_WITHOUT_MOJO,

Powered by Google App Engine
This is Rietveld 408576698