summaryrefslogtreecommitdiffstats
path: root/content/browser/security_exploit_browsertest.cc
diff options
context:
space:
mode:
authornick <nick@chromium.org>2014-11-13 20:11:49 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-14 04:13:06 +0000
commit4c8dfd482ad484f2402a5d9bea921870f3ea5d89 (patch)
tree539588cc49bc86d99d61391c3ac468c41eb55bda /content/browser/security_exploit_browsertest.cc
parentf0ba8deca9141fc42e0a9746395f6843541bcde0 (diff)
downloadchromium_src-4c8dfd482ad484f2402a5d9bea921870f3ea5d89.zip
chromium_src-4c8dfd482ad484f2402a5d9bea921870f3ea5d89.tar.gz
chromium_src-4c8dfd482ad484f2402a5d9bea921870f3ea5d89.tar.bz2
IPC: a way for security exploit browsertests to simulate the appearance of a malicious IPC.
Use this to add a SecurityExploitBrowserTest for http://crbug.com/429922 Fix SecurityExploitBrowserTests on Android. Re-enable SecurityExploitBrowserTests on Android, except for two issues (1) the new test, which is actually disabled because of http://crbug.com/432737, discovered while developing this CL and (2) SetWebUIProperty, which is disabled because of http://crbug.com/433068, also discovered while developing this CL. Moral of the story being: never try. BUG=429922,432737,338023,433068 TEST=content_browsertests Review URL: https://codereview.chromium.org/712713002 Cr-Commit-Position: refs/heads/master@{#304170}
Diffstat (limited to 'content/browser/security_exploit_browsertest.cc')
-rw-r--r--content/browser/security_exploit_browsertest.cc127
1 files changed, 121 insertions, 6 deletions
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 2a1be07..68430ad 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -4,14 +4,18 @@
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/interstitial_page.h"
+#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -19,6 +23,11 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.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"
+
+using IPC::IpcSecurityTestUtil;
namespace content {
@@ -35,10 +44,11 @@ namespace {
// the attempt is the return value.
RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
int* target_routing_id) {
- GURL foo("http://foo.com/files/simple_page.html");
+ GURL foo("http://foo.com/simple_page.html");
// Start off with initial navigation, so we get the first process allocated.
NavigateToURL(shell, foo);
+ EXPECT_EQ(base::ASCIIToUTF16("OK"), shell->web_contents()->GetTitle());
// Open another window, so we generate some more routing ids.
ShellAddedObserver shell2_observer;
@@ -55,7 +65,7 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
shell->web_contents()->GetRenderViewHost()->GetRoutingID());
// Now, simulate a link click coming from the renderer.
- GURL extension_url("https://bar.com/files/simple_page.html");
+ GURL extension_url("https://bar.com/simple_page.html");
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
wc->GetFrameTree()->root()->navigator()->RequestOpenURL(
wc->GetFrameTree()->root()->current_frame_host(), extension_url,
@@ -84,25 +94,37 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
class SecurityExploitBrowserTest : public ContentBrowserTest {
public:
SecurityExploitBrowserTest() {}
+
void SetUpCommandLine(CommandLine* command_line) override {
- ASSERT_TRUE(test_server()->Start());
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
// Add a host resolver rule to map all outgoing requests to the test server.
// This allows us to use "real" hostnames in URLs, which we can use to
// create arbitrary SiteInstances.
command_line->AppendSwitchASCII(
switches::kHostResolverRules,
- "MAP * " + test_server()->host_port_pair().ToString() +
+ "MAP * " +
+ net::HostPortPair::FromURL(embedded_test_server()->base_url())
+ .ToString() +
",EXCLUDE localhost");
}
};
+// Fails because the process kill on Android does not succeed.
+// http://crbug.com/433068
+#if defined(OS_ANDROID)
+#define MAYBE_SetWebUIProperty DISABLED_SetWebUIProperty
+#else
+#define MAYBE_SetWebUIProperty SetWebUIProperty
+#endif
+
// Ensure that we kill the renderer process if we try to give it WebUI
// properties and it doesn't have enabled WebUI bindings.
-IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, SetWebUIProperty) {
- GURL foo("http://foo.com/files/simple_page.html");
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MAYBE_SetWebUIProperty) {
+ GURL foo("http://foo.com/simple_page.html");
NavigateToURL(shell(), foo);
+ EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
EXPECT_EQ(0,
shell()->web_contents()->GetRenderViewHost()->GetEnabledBindings());
@@ -166,4 +188,97 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
// If the above operation doesn't crash, the test has succeeded!
}
+class SecurityExploitTestInterstitialPage : public InterstitialPageDelegate {
+ public:
+ explicit SecurityExploitTestInterstitialPage(WebContents* contents) {
+ InterstitialPage* interstitial = InterstitialPage::Create(
+ contents, true, contents->GetLastCommittedURL(), this);
+ interstitial->Show();
+ }
+
+ // InterstitialPageDelegate implementation.
+ void CommandReceived(const std::string& command) override {
+ last_command_ = command;
+ }
+
+ std::string GetHTMLContents() override {
+ return "<html><head><script>"
+ "window.domAutomationController.setAutomationId(1);"
+ "window.domAutomationController.send(\"okay\");"
+ "</script></head>"
+ "<body>this page is an interstitial</body></html>";
+ }
+
+ std::string last_command() { return last_command_; }
+
+ private:
+ std::string last_command_;
+ DISALLOW_COPY_AND_ASSIGN(SecurityExploitTestInterstitialPage);
+};
+
+// Fails due to InterstitialPage's reliance on PostNonNestableTask
+// http://crbug.com/432737
+#if defined(OS_ANDROID)
+#define MAYBE_InterstitialCommandFromUnderlyingContent \
+ DISABLED_InterstitialCommandFromUnderlyingContent
+#else
+#define MAYBE_InterstitialCommandFromUnderlyingContent \
+ InterstitialCommandFromUnderlyingContent
+#endif
+
+// The interstitial should not be controllable by the underlying content.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+ MAYBE_InterstitialCommandFromUnderlyingContent) {
+ // Start off with initial navigation, to allocate the process.
+ GURL foo("http://foo.com/simple_page.html");
+ NavigateToURL(shell(), foo);
+ EXPECT_EQ(base::ASCIIToUTF16("OK"), shell()->web_contents()->GetTitle());
+
+ DOMMessageQueue message_queue;
+
+ // Install and show an interstitial page.
+ SecurityExploitTestInterstitialPage* interstitial =
+ new SecurityExploitTestInterstitialPage(shell()->web_contents());
+
+ ASSERT_EQ("", interstitial->last_command());
+ content::WaitForInterstitialAttach(shell()->web_contents());
+
+ InterstitialPage* interstitial_page =
+ shell()->web_contents()->GetInterstitialPage();
+ ASSERT_TRUE(interstitial_page != NULL);
+ ASSERT_TRUE(shell()->web_contents()->ShowingInterstitialPage());
+ ASSERT_TRUE(interstitial_page->GetDelegateForTesting() == interstitial);
+
+ // The interstitial page ought to be able to send a message.
+ std::string message;
+ ASSERT_TRUE(message_queue.WaitForMessage(&message));
+ ASSERT_EQ("\"okay\"", message);
+ ASSERT_EQ("\"okay\"", interstitial->last_command());
+
+ // Send an automation message from the underlying content and wait for it to
+ // be dispatched on this thread. This message should not be received by the
+ // interstitial.
+ content::RenderFrameHost* compromised_renderer =
+ shell()->web_contents()->GetMainFrame();
+ FrameHostMsg_DomOperationResponse evil(compromised_renderer->GetRoutingID(),
+ "evil", MSG_ROUTING_NONE);
+ IpcSecurityTestUtil::PwnMessageReceived(
+ compromised_renderer->GetProcess()->GetChannel(), evil);
+
+ ASSERT_TRUE(message_queue.WaitForMessage(&message));
+ ASSERT_EQ("evil", message)
+ << "Automation message should be received by WebContents.";
+ ASSERT_EQ("\"okay\"", interstitial->last_command())
+ << "Interstitial should not be affected.";
+
+ // Send a second message from the interstitial page, and make sure that the
+ // "evil" message doesn't arrive in the intervening period.
+ ASSERT_TRUE(content::ExecuteScript(
+ interstitial_page->GetRenderViewHostForTesting(),
+ "window.domAutomationController.send(\"okay2\");"));
+ ASSERT_TRUE(message_queue.WaitForMessage(&message));
+ ASSERT_EQ("\"okay2\"", message);
+ ASSERT_EQ("\"okay2\"", interstitial->last_command());
+}
+
} // namespace content