blob: a3ed72d104433441576a7b39825e6241925049f3 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/extension_process_policy.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/common/fileapi/webblob_messages.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "ipc/ipc_security_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
// The goal of these tests is to "simulate" exploited renderer processes, which
// can send arbitrary IPC messages and confuse browser process internal state,
// leading to security bugs. We are trying to verify that the browser doesn't
// perform any dangerous operations in such cases.
// This is similar to the security_exploit_browsertest.cc tests, but also
// includes chrome/ layer concepts such as extensions.
class ChromeSecurityExploitBrowserTest : public InProcessBrowserTest {
public:
ChromeSecurityExploitBrowserTest() {}
~ChromeSecurityExploitBrowserTest() override {}
void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->Start());
host_resolver()->AddRule("*", "127.0.0.1");
}
void SetUpCommandLine(base::CommandLine* command_line) override {
// Since we assume exploited renderer process, it can bypass the same origin
// policy at will. Simulate that by passing the disable-web-security flag.
command_line->AppendSwitch(switches::kDisableWebSecurity);
}
private:
DISALLOW_COPY_AND_ASSIGN(ChromeSecurityExploitBrowserTest);
};
IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTest,
ChromeExtensionResources) {
// Load a page that requests a chrome-extension:// image through XHR. We
// expect this load to fail, as it is an illegal request.
GURL foo = embedded_test_server()->GetURL("foo.com",
"/chrome_extension_resource.html");
content::DOMMessageQueue msg_queue;
ui_test_utils::NavigateToURL(browser(), foo);
std::string status;
std::string expected_status("0");
EXPECT_TRUE(msg_queue.WaitForMessage(&status));
EXPECT_STREQ(status.c_str(), expected_status.c_str());
}
IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTest,
CreateBlobInExtensionOrigin) {
// This test relies on extensions documents running in extension processes,
// which is guaranteed with --isolate-extensions. Without it, the checks are
// not enforced and this test will time out waiting for the process to be
// killed.
if (!extensions::IsIsolateExtensionsEnabled())
return;
ui_test_utils::NavigateToURL(
browser(),
embedded_test_server()->GetURL("a.root-servers.net", "/title1.html"));
content::RenderFrameHost* rfh =
browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
// All these are attacker controlled values. The UUID is arbitrary.
std::string blob_id = "2ce53a26-0409-45a3-86e5-f8fb9f5566d8";
std::string blob_type = "text/html";
std::string blob_contents = "<script>chrome.extensions</script>";
std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
// Target the bookmark manager extension.
std::string target_origin =
"chrome-extension://eemcgdkfndhakfknompkggombfjjjeno";
std::vector<storage::DataElement> data_elements(1);
data_elements[0].SetToBytes(blob_contents.c_str(), blob_contents.size());
// Set up a blob ID and populate it with attacker-controlled value. This
// message is allowed, because this data is not in any origin.
IPC::IpcSecurityTestUtil::PwnMessageReceived(
rfh->GetProcess()->GetChannel(),
BlobStorageMsg_RegisterBlob(blob_id, blob_type, "", data_elements));
// This IPC should result in a kill because |target_origin| is not commitable
// in |rfh->GetProcess()|.
content::RenderProcessHostWatcher crash_observer(
rfh->GetProcess(),
content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
rfh->GetProcess()->GetChannel(),
BlobHostMsg_RegisterPublicURL(
GURL("blob:" + target_origin + "/" + blob_path), blob_id));
crash_observer.Wait(); // If the process is killed, this test passes.
}