Diff
Modified: trunk/LayoutTests/ChangeLog (113502 => 113503)
--- trunk/LayoutTests/ChangeLog 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/ChangeLog 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,25 @@
+2012-04-06 Tom Sepez <[email protected]>
+
+ Block cross-origin iframe scroll to fragment.
+ https://bugs.webkit.org/show_bug.cgi?id=73083
+
+ Reviewed by Adam Barth.
+
+ Add a restriction similar to what FF has done for all iframes for over a
+ year now. Our change is less disruptive in that it only does this in the
+ cross-orgin case, which is where the fragment scrolling is problematic.
+
+ * http/tests/inspector/resource-parameters-expected.txt:
+ * http/tests/navigation/anchor-frames-cross-origin-expected.txt: Added.
+ * http/tests/navigation/anchor-frames-cross-origin.html: Added.
+ * http/tests/navigation/resources/frame-with-anchor-cross-origin.html: Added.
+ * http/tests/security/xssAuditor/anchor-url-dom-write-location-expected.txt:
+ * http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-expected.txt:
+ * http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-null-char-expected.txt:
+ * http/tests/security/xssAuditor/anchor-url-dom-write-location-_javascript_-URL-expected.txt:
+ * http/tests/security/xssAuditor/anchor-url-dom-write-location2-expected.txt:
+ * http/tests/security/xssAuditor/dom-write-location-inline-event-expected.txt:
+
2012-04-06 Tony Chang <[email protected]>
[chromium] Unreviewed, remove a passing test.
Modified: trunk/LayoutTests/http/tests/inspector/resource-parameters-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/inspector/resource-parameters-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/inspector/resource-parameters-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Tests that resources panel shows form data parameters.
Added: trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin-expected.txt (0 => 113503)
--- trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin-expected.txt (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -0,0 +1,23 @@
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
+
+
+--------
+Frame: 'main'
+--------
+This prevents a cross-origin information leak sometimes know as framesniffing.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.body.offsetHeight > document.documentElement.clientHeight is true
+PASS document.body.scrollTop == 0 is true
+PASS document.body.scrollLeft == 0 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+This is an anchor point named "anchor1.
+
+--------
+Frame: 'footer'
+--------
+
Added: trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin.html (0 => 113503)
--- trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/anchor-frames-cross-origin.html 2012-04-06 22:15:02 UTC (rev 113503)
@@ -0,0 +1,11 @@
+<html>
+ <!-- See resources/frame-with-anchor-cross-origin.html for description of test -->
+ <script>
+ if (window.layoutTestController)
+ layoutTestController.dumpChildFramesAsText();
+ </script>
+ <frameset rows="90%,10%">
+ <frame src="" name="main">
+ <frame src="" name="footer">
+ </frameset>
+</html>
Added: trunk/LayoutTests/http/tests/navigation/resources/frame-with-anchor-cross-origin.html (0 => 113503)
--- trunk/LayoutTests/http/tests/navigation/resources/frame-with-anchor-cross-origin.html (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/resources/frame-with-anchor-cross-origin.html 2012-04-06 22:15:02 UTC (rev 113503)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src=""
+ <script>
+ function runTest() {
+ description('Tests that loading a cross-origin frame with a URL that contains a fragment pointed at a named anchor does not scroll to that anchor.');
+ description('This prevents a cross-origin information leak sometimes know as framesniffing.');
+
+ // Check scroll position in a timeout to make sure that the anchor has
+ // been scrolled to.
+ setTimeout(function() {
+ // Make sure that the body is taller than the viewport (i.e. scrolling is required).
+ shouldBeTrue('document.body.offsetHeight > document.documentElement.clientHeight');
+
+ // We must not be scrolled at all.
+ shouldBeTrue('document.body.scrollTop == 0');
+ shouldBeTrue('document.body.scrollLeft == 0');
+
+ finishJSTest();
+ }, 0);
+ }
+
+ var jsTestIsAsync = true;
+ </script>
+</head>
+<body _onload_="runTest()">
+<p id="description"></p>
+<div id="console"></div>
+
+<div style="height: 2000px">
+ <!-- Spacer to make sure that the named anchor below requires scrolling -->
+</div>
+
+<a name="anchor1">This is an anchor point named "anchor1</a>.
+<script src=""
+</body>
+</html>
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,4 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,5 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-null-char-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-null-char-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-inline-event-null-char-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,5 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-_javascript_-URL-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-_javascript_-URL-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location-_javascript_-URL-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,4 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location2-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location2-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/anchor-url-dom-write-location2-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,4 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/LayoutTests/http/tests/security/xssAuditor/dom-write-location-inline-event-expected.txt (113502 => 113503)
--- trunk/LayoutTests/http/tests/security/xssAuditor/dom-write-location-inline-event-expected.txt 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/LayoutTests/http/tests/security/xssAuditor/dom-write-location-inline-event-expected.txt 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,4 @@
CONSOLE MESSAGE: Refused to execute a _javascript_ script. Source code of script found within request.
+CONSOLE MESSAGE: Fragment navigation not allowed with cross-origin frames.
Modified: trunk/Source/WebCore/ChangeLog (113502 => 113503)
--- trunk/Source/WebCore/ChangeLog 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/Source/WebCore/ChangeLog 2012-04-06 22:15:02 UTC (rev 113503)
@@ -1,3 +1,32 @@
+2012-04-06 Tom Sepez <[email protected]>
+
+ Block cross-origin iframe scroll to fragment.
+ https://bugs.webkit.org/show_bug.cgi?id=73083
+
+ Reviewed by Adam Barth.
+
+ Add a restriction similar to what FF has done for all iframes for over a
+ year now. Our change is less disruptive in that it only does this in the
+ cross-orgin case, which is where the fragment scrolling is problematic.
+
+ Test: http/tests/navigation/anchor-frames-cross-origin.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::canBeAccessedByEveryAncestorFrame):
+ (WebCore):
+ * dom/Document.h:
+ (Document):
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::finishedParsing):
+ (WebCore::FrameLoader::loadInSameDocument):
+ (WebCore::FrameLoader::loadURL):
+ (WebCore::FrameLoader::loadWithDocumentLoader):
+ (WebCore::FrameLoader::shouldPerformFragmentNavigation):
+ (WebCore::FrameLoader::scrollToFragmentIfAllowed):
+ (WebCore):
+ * loader/FrameLoader.h:
+ (FrameLoader):
+
2012-04-03 Jer Noble <[email protected]>
Foreground of apple.com/iphone video page visible during full screen animation.
Modified: trunk/Source/WebCore/dom/Document.cpp (113502 => 113503)
--- trunk/Source/WebCore/dom/Document.cpp 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-04-06 22:15:02 UTC (rev 113503)
@@ -2686,6 +2686,15 @@
return false;
}
+bool Document::canBeAccessedByEveryAncestorFrame()
+{
+ for (Frame* ancestorFrame = m_frame->tree()->parent(); ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
+ if (!ancestorFrame->document()->securityOrigin()->canAccess(securityOrigin()))
+ return false;
+ }
+ return true;
+}
+
CSSStyleSheet* Document::pageUserSheet()
{
if (m_pageUserSheet)
Modified: trunk/Source/WebCore/dom/Document.h (113502 => 113503)
--- trunk/Source/WebCore/dom/Document.h 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/Source/WebCore/dom/Document.h 2012-04-06 22:15:02 UTC (rev 113503)
@@ -624,6 +624,7 @@
virtual void disableEval();
bool canNavigate(Frame* targetFrame);
+ bool canBeAccessedByEveryAncestorFrame();
CSSStyleSheet* pageUserSheet();
void clearPageUserSheet();
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (113502 => 113503)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2012-04-06 22:15:02 UTC (rev 113503)
@@ -683,7 +683,7 @@
// Check if the scrollbars are really needed for the content.
// If not, remove them, relayout, and repaint.
m_frame->view()->restoreScrollbar();
- m_frame->view()->scrollToFragment(m_frame->document()->url());
+ scrollToFragmentIfAllowed(m_frame->document()->url());
}
void FrameLoader::loadDone()
@@ -1028,7 +1028,7 @@
// based on the current request. Must also happen before we openURL and displace the
// scroll position, since adding the BF item will save away scroll state.
- // NB2: If we were loading a long, slow doc, and the user anchor nav'ed before
+ // NB2: If we were loading a long, slow doc, and the user fragment navigated before
// it was done, currItem is now set the that slow doc, and prevItem is whatever was
// before it. Adding the b/f item will bump the slow doc down to prevItem, even
// though its load is not yet done. I think this all works out OK, for one because
@@ -1052,16 +1052,15 @@
// We need to scroll to the fragment whether or not a hash change occurred, since
// the user might have scrolled since the previous navigation.
- if (FrameView* view = m_frame->view())
- view->scrollToFragment(url);
+ scrollToFragmentIfAllowed(url);
m_isComplete = false;
checkCompleted();
if (isNewNavigation) {
// This will clear previousItem from the rest of the frame tree that didn't
- // doing any loading. We need to make a pass on this now, since for anchor nav
- // we'll not go through a real load and reach Completed state.
+ // doing any loading. We need to make a pass on this now, since for fragment
+ // navigation we'll not go through a real load and reach Completed state.
checkLoadComplete();
}
@@ -1235,10 +1234,10 @@
bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
const String& httpMethod = request.httpMethod();
- // Make sure to do scroll to anchor processing even if the URL is
+ // Make sure to do scroll to fragment processing even if the URL is
// exactly the same so pages with '#' links and DHTML side effects
// work properly.
- if (shouldScrollToAnchor(isFormSubmission, httpMethod, newLoadType, newURL)) {
+ if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
oldDocumentLoader->setTriggeringAction(action);
policyChecker()->stopCheck();
policyChecker()->setLoadType(newLoadType);
@@ -1377,7 +1376,7 @@
const KURL& newURL = loader->request().url();
const String& httpMethod = loader->request().httpMethod();
- if (shouldScrollToAnchor(isFormSubmission, httpMethod, policyChecker()->loadType(), newURL)) {
+ if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker()->loadType(), newURL)) {
RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
NavigationAction action(loader->request(), policyChecker()->loadType(), isFormSubmission);
@@ -2664,10 +2663,8 @@
loadInSameDocument(request.url(), 0, !isRedirect);
}
-bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
+bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
{
- // Should we do anchor navigation within the existing content?
-
// We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
// currently displaying a frameset, or if the URL does not have a fragment.
// These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
@@ -2684,6 +2681,22 @@
&& !m_frame->document()->isFrameSet();
}
+void FrameLoader::scrollToFragmentIfAllowed(const KURL& url)
+{
+ FrameView* view = m_frame->view();
+ if (!view)
+ return;
+
+ // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
+ if (url.hasFragmentIdentifier() && !m_frame->document()->canBeAccessedByEveryAncestorFrame()) {
+ DEFINE_STATIC_LOCAL(String, consoleMessage, ("Fragment navigation not allowed with cross-origin frames."));
+ m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage);
+ return;
+ }
+
+ view->scrollToFragment(url);
+}
+
void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
{
Modified: trunk/Source/WebCore/loader/FrameLoader.h (113502 => 113503)
--- trunk/Source/WebCore/loader/FrameLoader.h 2012-04-06 21:49:13 UTC (rev 113502)
+++ trunk/Source/WebCore/loader/FrameLoader.h 2012-04-06 22:15:02 UTC (rev 113503)
@@ -321,7 +321,8 @@
void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue);
void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);
- bool shouldScrollToAnchor(bool isFormSubmission, const String& httpMethod, FrameLoadType, const KURL&);
+ bool shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType, const KURL&);
+ void scrollToFragmentIfAllowed(const KURL&);
void checkLoadCompleteForThisFrame();