Source/WebCore: chromium WebFrameImpl - don't load javascript URLs against chrome...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Aug 2011 21:06:43 +0000 (21:06 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Aug 2011 21:06:43 +0000 (21:06 +0000)
pages.  Adds a mechanism for registering sensitive schemes which should
not be subject to manipulation by javascript urls typed into a location bar
or, more importantly, their bookmarklet equivalents.
https://bugs.webkit.org/show_bug.cgi?id=66720

Patch by Tom Sepez <tsepez@chromium.org> on 2011-08-24
Reviewed by Adam Barth.

Test: Chromium WebKit API unit test in chromium specific directory.

* platform/SchemeRegistry.cpp:
(WebCore::notAllowingJavascriptURLsSchemes):
(WebCore::SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs):
(WebCore::SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs):
* platform/SchemeRegistry.h:

Source/WebKit/chromium: chromium WebFrameImpl - don't load javascript URLs against chrome internal pages.
https://bugs.webkit.org/show_bug.cgi?id=66720

Patch by Tom Sepez <tsepez@chromium.org> on 2011-08-24
Reviewed by Adam Barth.

* public/WebSecurityPolicy.h:
* src/WebFrameImpl.cpp:
(WebKit::WebFrameImpl::loadJavaScriptURL):
* src/WebSecurityPolicy.cpp:
(WebKit::WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs):
* tests/WebFrameTest.cpp:
(WebKit::WebFrameTest::WebFrameTest):
(WebKit::WebFrameTest::registerMockedHttpURLLoad):
(WebKit::WebFrameTest::registerMockedChromeURLLoad):
(WebKit::WebFrameTest::serveRequests):
(WebKit::WebFrameTest::loadHttpFrame):
(WebKit::WebFrameTest::loadChromeFrame):
(WebKit::WebFrameTest::registerMockedURLLoad):
(WebKit::WebFrameTest::loadFrame):
(WebKit::TEST_F):
* tests/data/history.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@93734 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/SchemeRegistry.cpp
Source/WebCore/platform/SchemeRegistry.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/public/WebSecurityPolicy.h
Source/WebKit/chromium/src/WebFrameImpl.cpp
Source/WebKit/chromium/src/WebSecurityPolicy.cpp
Source/WebKit/chromium/tests/WebFrameTest.cpp
Source/WebKit/chromium/tests/data/history.html [new file with mode: 0644]

index 83783b9556365913326914d5f0889ae1976c4c03..cf00303ed824bb2ff4b00e015df27bb23e8823b8 100644 (file)
@@ -1,3 +1,21 @@
+2011-08-24  Tom Sepez  <tsepez@chromium.org>
+
+        chromium WebFrameImpl - don't load javascript URLs against chrome internal
+        pages.  Adds a mechanism for registering sensitive schemes which should 
+        not be subject to manipulation by javascript urls typed into a location bar
+        or, more importantly, their bookmarklet equivalents.
+        https://bugs.webkit.org/show_bug.cgi?id=66720
+
+        Reviewed by Adam Barth.
+
+        Test: Chromium WebKit API unit test in chromium specific directory.
+        
+        * platform/SchemeRegistry.cpp:
+        (WebCore::notAllowingJavascriptURLsSchemes):
+        (WebCore::SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs):
+        (WebCore::SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs):
+        * platform/SchemeRegistry.h:
+
 2011-08-24  Alexandru Chiculita  <achicu@adobe.com>
 
         [CSSRegions] Fix Element::getBoundingClientRect and Element::getClientRects for content flow
index 2bc655e9014f04faf8f7e330dcfd03f38bfb9249..634f459ae37b2420023bb668594a5d9dd9c54215 100644 (file)
@@ -104,6 +104,12 @@ static URLSchemesMap& canDisplayOnlyIfCanRequestSchemes()
     return canDisplayOnlyIfCanRequestSchemes;
 }
 
+static URLSchemesMap& notAllowingJavascriptURLsSchemes()
+{
+    DEFINE_STATIC_LOCAL(URLSchemesMap, notAllowingJavascriptURLsSchemes, ());
+    return notAllowingJavascriptURLsSchemes;
+}
+
 void SchemeRegistry::registerURLSchemeAsLocal(const String& scheme)
 {
     localURLSchemes().add(scheme);
@@ -192,4 +198,16 @@ void SchemeRegistry::registerAsCanDisplayOnlyIfCanRequest(const String& scheme)
     canDisplayOnlyIfCanRequestSchemes().add(scheme);
 }
 
+void SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(const String& scheme) 
+{
+    notAllowingJavascriptURLsSchemes().add(scheme);
+}
+
+bool SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(const String& scheme)
+{
+    if (scheme.isEmpty())
+        return false;
+    return notAllowingJavascriptURLsSchemes().contains(scheme);
+}
+
 } // namespace WebCore
index c9cb476a03ff1a636fcd5da67111def35349729b..8b330a07154efe5f550bd57fb49cb1c4016f62ec 100644 (file)
@@ -63,6 +63,11 @@ public:
     // passed to SecurityOrigin::canDisplay.
     static bool canDisplayOnlyIfCanRequest(const String& scheme);
     static void registerAsCanDisplayOnlyIfCanRequest(const String& scheme);
+
+    // Schemes against which javascript: URLs should not be allowed to run (stop
+    // bookmarklets from running on sensitive pages). 
+    static void registerURLSchemeAsNotAllowingJavascriptURLs(const String& scheme);
+    static bool shouldTreatURLSchemeAsNotAllowingJavascriptURLs(const String& scheme);
 };
 
 } // namespace WebCore
index ec4cad5fbdd7ffe2258b3c33f83867c5b1583194..0889b553faa0a82f011b210e10e06c746749a12e 100644 (file)
@@ -1,3 +1,27 @@
+2011-08-24  Tom Sepez  <tsepez@chromium.org>
+
+        chromium WebFrameImpl - don't load javascript URLs against chrome internal pages.
+        https://bugs.webkit.org/show_bug.cgi?id=66720
+
+        Reviewed by Adam Barth.
+
+        * public/WebSecurityPolicy.h:
+        * src/WebFrameImpl.cpp:
+        (WebKit::WebFrameImpl::loadJavaScriptURL):
+        * src/WebSecurityPolicy.cpp:
+        (WebKit::WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs):
+        * tests/WebFrameTest.cpp:
+        (WebKit::WebFrameTest::WebFrameTest):
+        (WebKit::WebFrameTest::registerMockedHttpURLLoad):
+        (WebKit::WebFrameTest::registerMockedChromeURLLoad):
+        (WebKit::WebFrameTest::serveRequests):
+        (WebKit::WebFrameTest::loadHttpFrame):
+        (WebKit::WebFrameTest::loadChromeFrame):
+        (WebKit::WebFrameTest::registerMockedURLLoad):
+        (WebKit::WebFrameTest::loadFrame):
+        (WebKit::TEST_F):
+        * tests/data/history.html: Added.
+
 2011-08-24  Jeremy Apthorp  <jeremya@google.com>
 
         Expose fullscreen API on WebElement/WebDocument
index b1527204b391790b2be7d05e952028ae0c521d92..735b6e0328df01be9c3c748eda9d9451fcd7bbfb 100644 (file)
@@ -73,6 +73,10 @@ public:
     // based on their respective protocols.
     WEBKIT_EXPORT static bool shouldHideReferrer(const WebURL& url, const WebString& referrer);
 
+    // Registers an URL scheme to not allow manipulation of the loaded page
+    // by bookmarklets or javascript: URLs typed in the omnibox.
+    WEBKIT_EXPORT static void registerURLSchemeAsNotAllowingJavascriptURLs(const WebString&);
+
 private:
     WebSecurityPolicy();
 };
index 1fb66da03257f950af65f6822649d03a724c3ded..fbefdb61d7666a13199ab9b19e3ae835861b8ba6 100644 (file)
 #include "ResourceRequest.h"
 #include "SVGDocumentExtensions.h"
 #include "SVGSMILElement.h"
+#include "SchemeRegistry.h"
 #include "ScriptController.h"
 #include "ScriptSourceCode.h"
 #include "ScriptValue.h"
@@ -2295,6 +2296,10 @@ void WebFrameImpl::loadJavaScriptURL(const KURL& url)
     if (!m_frame->document() || !m_frame->page())
         return;
 
+    // Protect privileged pages against bookmarklets and other javascript manipulations.
+    if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(m_frame->document()->url().protocol()))
+        return;
+
     String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
     ScriptValue result = m_frame->script()->executeScript(script, true);
 
index 8e4e70208ee87590a0d2d8a977f3e8c4d3d69f27..3e8fc1a0f247c27a19031c05c2a394c3ba591cdc 100644 (file)
@@ -94,4 +94,9 @@ bool WebSecurityPolicy::shouldHideReferrer(const WebURL& url, const WebString& r
     return SecurityOrigin::shouldHideReferrer(url, referrer);
 }
 
+void WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(const WebString& scheme)
+{
+    SchemeRegistry::registerURLSchemeAsNotAllowingJavascriptURLs(scheme);
+}
+
 } // namespace WebKit
index 9446120a13f6dd698d53991181a34d867a7345fa..d7eec8a0c4566170224537025ad652825eed748b 100644 (file)
@@ -35,6 +35,7 @@
 #include "WebFrame.h"
 #include "WebFrameClient.h"
 #include "WebSearchableFormData.h"
+#include "WebSecurityPolicy.h"
 #include "WebSettings.h"
 #include "WebString.h"
 #include "WebURL.h"
@@ -53,7 +54,8 @@ namespace {
 class WebFrameTest : public testing::Test {
 public:
     WebFrameTest()
-        : baseURL("http://www.test.com/")
+        : baseURL("http://www.test.com/"),
+          chromeURL("chrome://")
     {
     }
 
@@ -62,7 +64,32 @@ public:
         webkit_support::UnregisterAllMockedURLs();
     }
 
-    void registerMockedURLLoad(const std::string& fileName)
+    void registerMockedHttpURLLoad(const std::string& fileName)
+    {
+        registerMockedURLLoad(baseURL, fileName);
+    }
+
+    void registerMockedChromeURLLoad(const std::string& fileName)
+    {
+        registerMockedURLLoad(chromeURL, fileName);
+    }
+
+    void serveRequests()
+    {
+        webkit_support::ServeAsynchronousMockedRequests();
+    }
+
+    void loadHttpFrame(WebFrame* frame, const std::string& fileName)
+    {
+        loadFrame(frame, baseURL, fileName);
+    }
+
+    void loadChromeFrame(WebFrame* frame, const std::string& fileName)
+    {
+        loadFrame(frame, chromeURL, fileName);
+    }
+
+    void registerMockedURLLoad(const std::string& base, const std::string& fileName)
     {
         WebURLResponse response;
         response.initialize();
@@ -72,24 +99,20 @@ public:
         filePath += "/Source/WebKit/chromium/tests/data/";
         filePath += fileName;
 
-        webkit_support::RegisterMockedURL(WebURL(GURL(baseURL + fileName)), response, WebString::fromUTF8(filePath));
-    }
-
-    void serveRequests()
-    {
-        webkit_support::ServeAsynchronousMockedRequests();
+        webkit_support::RegisterMockedURL(WebURL(GURL(base + fileName)), response, WebString::fromUTF8(filePath));
     }
 
-    void loadFrame(WebFrame* frame, const std::string& fileName)
+    void loadFrame(WebFrame* frame, const std::string& base, const std::string& fileName)
     {
         WebURLRequest urlRequest;
         urlRequest.initialize();
-        urlRequest.setURL(WebURL(GURL(baseURL + fileName)));
+        urlRequest.setURL(WebURL(GURL(base + fileName)));
         frame->loadRequest(urlRequest);
     }
 
 protected:
     std::string baseURL;
+    std::string chromeURL;
 };
 
 class TestWebFrameClient : public WebFrameClient {
@@ -97,17 +120,17 @@ class TestWebFrameClient : public WebFrameClient {
 
 TEST_F(WebFrameTest, ContentText)
 {
-    registerMockedURLLoad("iframes_test.html");
-    registerMockedURLLoad("visible_iframe.html");
-    registerMockedURLLoad("invisible_iframe.html");
-    registerMockedURLLoad("zero_sized_iframe.html");
+    registerMockedHttpURLLoad("iframes_test.html");
+    registerMockedHttpURLLoad("visible_iframe.html");
+    registerMockedHttpURLLoad("invisible_iframe.html");
+    registerMockedHttpURLLoad("zero_sized_iframe.html");
 
     // Create and initialize the WebView.
     TestWebFrameClient webFrameClient;
     WebView* webView = WebView::create(0);
     webView->initializeMainFrame(&webFrameClient);
 
-    loadFrame(webView->mainFrame(), "iframes_test.html");
+    loadHttpFrame(webView->mainFrame(), "iframes_test.html");
     serveRequests();
 
     // Now retrieve the frames text and test it only includes visible elements.
@@ -123,18 +146,18 @@ TEST_F(WebFrameTest, ContentText)
 
 TEST_F(WebFrameTest, FrameForEnteredContext)
 {
-    registerMockedURLLoad("iframes_test.html");
-    registerMockedURLLoad("visible_iframe.html");
-    registerMockedURLLoad("invisible_iframe.html");
-    registerMockedURLLoad("zero_sized_iframe.html");
+    registerMockedHttpURLLoad("iframes_test.html");
+    registerMockedHttpURLLoad("visible_iframe.html");
+    registerMockedHttpURLLoad("invisible_iframe.html");
+    registerMockedHttpURLLoad("zero_sized_iframe.html");
 
     // Create and initialize the WebView.
-    TestWebFrameClient webFrameClient;
+     TestWebFrameClient webFrameClient;
     WebView* webView = WebView::create(0);
     webView->settings()->setJavaScriptEnabled(true);
     webView->initializeMainFrame(&webFrameClient);
 
-    loadFrame(webView->mainFrame(), "iframes_test.html");
+    loadHttpFrame(webView->mainFrame(), "iframes_test.html");
     serveRequests();
 
     v8::HandleScope scope;
@@ -150,13 +173,13 @@ TEST_F(WebFrameTest, FrameForEnteredContext)
 
 TEST_F(WebFrameTest, FormWithNullFrame)
 {
-    registerMockedURLLoad("form.html");
+    registerMockedHttpURLLoad("form.html");
 
     TestWebFrameClient webFrameClient;
     WebView* webView = WebView::create(0);
     webView->initializeMainFrame(&webFrameClient);
 
-    loadFrame(webView->mainFrame(), "form.html");
+    loadHttpFrame(webView->mainFrame(), "form.html");
     serveRequests();
 
     WebVector<WebFormElement> forms;
@@ -169,4 +192,27 @@ TEST_F(WebFrameTest, FormWithNullFrame)
     WebSearchableFormData searchableDataForm(forms[0]);
 }
 
+TEST_F(WebFrameTest, ChromePageNoJavascript)
+{
+    registerMockedChromeURLLoad("history.html");
+
+    // Create and initialize the WebView.
+    TestWebFrameClient webFrameClient;
+    WebView* webView = WebView::create(0);
+    webView->settings()->setJavaScriptEnabled(true);
+    webView->initializeMainFrame(&webFrameClient);
+
+    loadChromeFrame(webView->mainFrame(), "history.html");
+    serveRequests();
+
+    // Try to run JS against the chrome-style URL.
+    WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs("chrome");
+    loadFrame(webView->mainFrame(), "javascript:", "document.body.appendChild(document.createTextNode('Clobbered'))");
+
+    // Now retrieve the frames text and see if it was clobbered.
+    std::string content = webView->mainFrame()->contentAsText(1024).utf8();
+    EXPECT_NE(std::string::npos, content.find("Simulated Chromium History Page"));
+    EXPECT_EQ(std::string::npos, content.find("Clobbered"));
 }
+
+} // namespace
diff --git a/Source/WebKit/chromium/tests/data/history.html b/Source/WebKit/chromium/tests/data/history.html
new file mode 100644 (file)
index 0000000..69b5faf
--- /dev/null
@@ -0,0 +1,3 @@
+<body>
+Simulated Chromium History Page
+</body>