Resource loader should block HTTP redirects to local resources
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Oct 2011 18:00:32 +0000 (18:00 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Oct 2011 18:00:32 +0000 (18:00 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68706

Patch by Ken Buchanan <kenrb@chromium.org> on 2011-10-03
Reviewed by Adam Barth.

Source/WebCore:

Modified MainResourceLoader to add an extra security check on
HTTP redirects. Also, moved isFeedWithNestedProtocolInHTTPFamily
to SecurityOrigin.cpp.

* loader/FrameLoader.cpp:
(WebCore::isFeedWithNestedProtocolInHTTPFamily):
(WebCore::FrameLoader::loadFrameRequest):
* loader/MainResourceLoader.cpp:
(WebCore::MainResourceLoader::willSendRequest):
* page/SecurityOrigin.cpp:
(WebCore::isFeedWithNestedProtocolInHTTPFamily):
(WebCore::SecurityOrigin::canDisplay):

LayoutTests:

Adding a test to attempt an HTTP redirect to a file: URL.

* http/tests/security/redirect-BLOCKED-to-localURL.html: Added.
* http/tests/security/redirect-BLOCKED-to-localURL-expected.txt: Added.
* http/tests/security/resources/file-redirect-target.html: Added.

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

LayoutTests/ChangeLog [changed mode: 0644->0755]
LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt [new file with mode: 0755]
LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL.html [new file with mode: 0755]
LayoutTests/http/tests/security/resources/file-redirect-target.html [new file with mode: 0755]
Source/WebCore/ChangeLog [changed mode: 0644->0755]
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/MainResourceLoader.cpp
Source/WebCore/page/SecurityOrigin.cpp

old mode 100644 (file)
new mode 100755 (executable)
index ae4701a..8d13cd6
@@ -1,3 +1,16 @@
+2011-10-03 Ken Buchanan <kenrb@chromium.org>
+
+        Resource loader should block HTTP redirects to local resources
+        https://bugs.webkit.org/show_bug.cgi?id=68706
+
+        Reviewed by Adam Barth.
+
+        Adding a test to attempt an HTTP redirect to a file: URL.
+
+        * http/tests/security/redirect-BLOCKED-to-localURL.html: Added.
+        * http/tests/security/redirect-BLOCKED-to-localURL-expected.txt: Added.
+        * http/tests/security/resources/file-redirect-target.html: Added.
+
 2011-10-04  Adam Barth  <abarth@webkit.org>
 
         Restore Linux baseline for this test.  The Linux baseline got clobbered
diff --git a/LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt b/LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt
new file mode 100755 (executable)
index 0000000..53f8772
--- /dev/null
@@ -0,0 +1,3 @@
+CONSOLE MESSAGE: line 0: Not allowed to load local resource: file-redirect-target.html
+
+This attempts to open a redirect link to a file URL, which should be blocked.
diff --git a/LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL.html b/LayoutTests/http/tests/security/redirect-BLOCKED-to-localURL.html
new file mode 100755 (executable)
index 0000000..b19a268
--- /dev/null
@@ -0,0 +1,11 @@
+<html>
+<body>
+<iframe src="http://127.0.0.1:8000/security/resources/redir.php?url=file:///tmp/LayoutTests/http/tests/security/resources/file-redirect-target.html"></iframe></br>
+<script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+    }
+</script>
+<p>This attempts to open a redirect link to a file URL, which should be blocked.</p>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/resources/file-redirect-target.html b/LayoutTests/http/tests/security/resources/file-redirect-target.html
new file mode 100755 (executable)
index 0000000..73e534b
--- /dev/null
@@ -0,0 +1,3 @@
+<html>
+FAIL: This page shouldn't load via HTTP redirect to file:
+</html>
old mode 100644 (file)
new mode 100755 (executable)
index d15bc9b..c1e58db
@@ -1,3 +1,23 @@
+2011-10-03 Ken Buchanan <kenrb@chromium.org>
+
+        Resource loader should block HTTP redirects to local resources
+        https://bugs.webkit.org/show_bug.cgi?id=68706
+
+        Reviewed by Adam Barth.
+
+        Modified MainResourceLoader to add an extra security check on
+        HTTP redirects. Also, moved isFeedWithNestedProtocolInHTTPFamily
+        to SecurityOrigin.cpp.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::isFeedWithNestedProtocolInHTTPFamily):
+        (WebCore::FrameLoader::loadFrameRequest):
+        * loader/MainResourceLoader.cpp:
+        (WebCore::MainResourceLoader::willSendRequest):
+        * page/SecurityOrigin.cpp:
+        (WebCore::isFeedWithNestedProtocolInHTTPFamily):
+        (WebCore::SecurityOrigin::canDisplay):
+
 2011-10-04  Cary Clark  <caryclark@google.com>
 
         Apply color profile found to decoded bitmap (Skia on Mac)
index baaf202..4a52002 100644 (file)
@@ -1125,21 +1125,6 @@ void FrameLoader::setupForReplace()
     detachChildren();
 }
 
-// This is a hack to allow keep navigation to http/https feeds working. To remove this
-// we need to introduce new API akin to registerURLSchemeAsLocal, that registers a
-// protocols navigation policy.
-static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url)
-{
-    const String& urlString = url.string();
-    if (!urlString.startsWith("feed", false))
-        return false;
-
-    return urlString.startsWith("feed://", false) 
-        || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false)
-        || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false)
-        || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false);
-}
-
 void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList,
     PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy)
 {    
@@ -1149,8 +1134,7 @@ void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHis
     KURL url = request.resourceRequest().url();
 
     ASSERT(m_frame->document());
-    // FIXME: Should we move the isFeedWithNestedProtocolInHTTPFamily logic inside SecurityOrigin::canDisplay?
-    if (!isFeedWithNestedProtocolInHTTPFamily(url) && !request.requester()->canDisplay(url)) {
+    if (!request.requester()->canDisplay(url)) {
         reportLocalLoadFailed(m_frame, url.string());
         return;
     }
index 5810c55..c596249 100644 (file)
@@ -182,6 +182,15 @@ void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const Reso
 
     ASSERT(documentLoader()->timing()->fetchStart);
     if (!redirectResponse.isNull()) {
+        // If the redirecting url is not allowed to display content from the target origin,
+        // then block the redirect.
+        RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
+        if (!redirectingOrigin->canDisplay(newRequest.url())) {
+            FrameLoader::reportLocalLoadFailed(m_frame.get(), newRequest.url().string());
+            cancel();
+            return;
+        }
+
         DocumentLoadTiming* documentLoadTiming = documentLoader()->timing();
 
         // Check if the redirected url is allowed to access the redirecting url's timing information.
index a58e970..73a5d9a 100644 (file)
@@ -332,10 +332,33 @@ bool SecurityOrigin::isAccessToURLWhiteListed(const KURL& url) const
     return isAccessWhiteListed(targetOrigin.get());
 }
 
+// This is a hack to allow keep navigation to http/https feeds working. To remove this
+// we need to introduce new API akin to registerURLSchemeAsLocal, that registers a
+// protocols navigation policy.
+// feed(|s|search): is considered a 'nesting' scheme by embedders that support it, so it can be
+// local or remote depending on what is nested. Currently we just check if we are nesting
+// http or https, otherwise we ignore the nesting for the purpose of a security check. We need
+// a facility for registering nesting schemes, and some generalized logic for them.
+// This function should be removed as an outcome of https://bugs.webkit.org/show_bug.cgi?id=69196
+static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url)
+{
+    const String& urlString = url.string();
+    if (!urlString.startsWith("feed", false))
+        return false;
+
+    return urlString.startsWith("feed://", false) 
+        || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false)
+        || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false)
+        || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false);
+}
+
 bool SecurityOrigin::canDisplay(const KURL& url) const
 {
     String protocol = url.protocol().lower();
 
+    if (isFeedWithNestedProtocolInHTTPFamily(url))
+        return true;
+
     if (SchemeRegistry::canDisplayOnlyIfCanRequest(protocol))
         return canRequest(url);