⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 245346 in webkit


Ignore:
Timestamp:
May 15, 2019, 2:44:36 PM (7 years ago)
Author:
Alan Coon
Message:

Cherry-pick r239742. rdar://problem/50753925

Prevent cross-site top-level navigations from third-party iframes
https://bugs.webkit.org/show_bug.cgi?id=193076
<rdar://problem/36074736>

Reviewed by Alex Christensen.

Source/WebCore:

Prevent cross-site top-level navigations from third-party iframes if the following conditions are met:

  1. Its tries to navigate the top-level page cross-site (different eTDL+1)
  2. The user has never interacted with the third-party iframe or any of its subframes

This experiment's intent is to block suspicious main-frame navigations by third-party content. The feature
is behind a runtime experimental feature flag, on by default.

Tests: http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html

http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html
http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html
http/tests/security/block-top-level-navigations-by-third-party-iframes.html

  • dom/Document.cpp: (WebCore::printNavigationErrorMessage): (WebCore::Document::canNavigate): (WebCore::Document::canNavigateInternal): (WebCore::Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking):
  • dom/Document.h:
  • dom/UserGestureIndicator.cpp:
  • page/DOMWindow.cpp: (WebCore::DOMWindow::setLocation):
  • page/DOMWindow.h:
  • page/Frame.h:
  • page/Location.cpp: (WebCore::Location::replace): (WebCore::Location::setLocation):
  • page/Settings.yaml:

Source/WebKit:

Add experimental feature flag, on by default.

  • Shared/WebPreferences.yaml:

LayoutTests:

Add layout test coverage.

  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin-expected.txt: Added.
  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html: Added.
  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation-expected.txt: Added.
  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html: Added.
  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation-expected.txt: Added.
  • http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html: Added.
  • http/tests/security/block-top-level-navigations-by-third-party-iframes-expected.txt: Added.
  • http/tests/security/block-top-level-navigations-by-third-party-iframes.html: Added.
  • http/tests/security/resources/navigate-top-level-frame-to-failure-page.html: Added.
  • http/tests/security/resources/navigate-top-level-frame-to-success-page-same-origin.html: Added.
  • http/tests/security/resources/navigate-top-level-frame-to-success-page-with-previous-user-gesture.html: Added.
  • http/tests/security/resources/navigate-top-level-frame-to-success-page-with-user-gesture.html: Added.
  • http/tests/security/resources/should-have-loaded.html: Added.
  • http/tests/security/resources/should-not-have-loaded.html: Added.

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

Location:
branches/safari-607-branch
Files:
14 added
17 edited

Legend:

Unmodified
Added
Removed
  • branches/safari-607-branch/LayoutTests/ChangeLog

    r244798 r245346  
     12019-05-14  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Cherry-pick r239742. rdar://problem/50753925
     4
     5    Prevent cross-site top-level navigations from third-party iframes
     6    https://bugs.webkit.org/show_bug.cgi?id=193076
     7    <rdar://problem/36074736>
     8   
     9    Reviewed by Alex Christensen.
     10   
     11    Source/WebCore:
     12   
     13    Prevent cross-site top-level navigations from third-party iframes if the following conditions are met:
     14    1. Its tries to navigate the top-level page cross-site (different eTDL+1)
     15    2. The user has never interacted with the third-party iframe or any of its subframes
     16   
     17    This experiment's intent is to block suspicious main-frame navigations by third-party content. The feature
     18    is behind a runtime experimental feature flag, on by default.
     19   
     20    Tests: http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html
     21           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html
     22           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html
     23           http/tests/security/block-top-level-navigations-by-third-party-iframes.html
     24   
     25    * dom/Document.cpp:
     26    (WebCore::printNavigationErrorMessage):
     27    (WebCore::Document::canNavigate):
     28    (WebCore::Document::canNavigateInternal):
     29    (WebCore::Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking):
     30    * dom/Document.h:
     31    * dom/UserGestureIndicator.cpp:
     32    * page/DOMWindow.cpp:
     33    (WebCore::DOMWindow::setLocation):
     34    * page/DOMWindow.h:
     35    * page/Frame.h:
     36    * page/Location.cpp:
     37    (WebCore::Location::replace):
     38    (WebCore::Location::setLocation):
     39    * page/Settings.yaml:
     40   
     41    Source/WebKit:
     42   
     43    Add experimental feature flag, on by default.
     44   
     45    * Shared/WebPreferences.yaml:
     46   
     47    LayoutTests:
     48   
     49    Add layout test coverage.
     50   
     51    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin-expected.txt: Added.
     52    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html: Added.
     53    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation-expected.txt: Added.
     54    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html: Added.
     55    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation-expected.txt: Added.
     56    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html: Added.
     57    * http/tests/security/block-top-level-navigations-by-third-party-iframes-expected.txt: Added.
     58    * http/tests/security/block-top-level-navigations-by-third-party-iframes.html: Added.
     59    * http/tests/security/resources/navigate-top-level-frame-to-failure-page.html: Added.
     60    * http/tests/security/resources/navigate-top-level-frame-to-success-page-same-origin.html: Added.
     61    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-previous-user-gesture.html: Added.
     62    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-user-gesture.html: Added.
     63    * http/tests/security/resources/should-have-loaded.html: Added.
     64    * http/tests/security/resources/should-not-have-loaded.html: Added.
     65   
     66   
     67    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239742 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     68
     69    2019-01-08  Chris Dumez  <cdumez@apple.com>
     70
     71            Prevent cross-site top-level navigations from third-party iframes
     72            https://bugs.webkit.org/show_bug.cgi?id=193076
     73            <rdar://problem/36074736>
     74
     75            Reviewed by Alex Christensen.
     76
     77            Add layout test coverage.
     78
     79            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin-expected.txt: Added.
     80            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html: Added.
     81            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation-expected.txt: Added.
     82            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html: Added.
     83            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation-expected.txt: Added.
     84            * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html: Added.
     85            * http/tests/security/block-top-level-navigations-by-third-party-iframes-expected.txt: Added.
     86            * http/tests/security/block-top-level-navigations-by-third-party-iframes.html: Added.
     87            * http/tests/security/resources/navigate-top-level-frame-to-failure-page.html: Added.
     88            * http/tests/security/resources/navigate-top-level-frame-to-success-page-same-origin.html: Added.
     89            * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-previous-user-gesture.html: Added.
     90            * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-user-gesture.html: Added.
     91            * http/tests/security/resources/should-have-loaded.html: Added.
     92            * http/tests/security/resources/should-not-have-loaded.html: Added.
     93
    1942019-04-24  Alan Coon  <alancoon@apple.com>
    295
  • branches/safari-607-branch/LayoutTests/http/tests/cookies/same-site/resources/click-hyperlink.php

    r230944 r245346  
    1414?>
    1515<a href="<?php echo $_GET['href']; ?>" <?php echo $targetAttribute; ?>>Click</a>
    16 <script>document.querySelector("a").click()</script>
     16<script>
     17internals.withUserGesture(() => {
     18    document.querySelector("a").click();
     19});
     20</script>
    1721</body>
    1822</html>
  • branches/safari-607-branch/LayoutTests/http/tests/security/frameNavigation/resources/iframe-that-performs-parent-navigation.html

    r120174 r245346  
    1212        function performTest()
    1313        {
    14             parent.location = "http://localhost:8000/security/frameNavigation/resources/navigation-changed-iframe.html";
     14            internals.withUserGesture(() => {
     15                parent.location = "http://localhost:8000/security/frameNavigation/resources/navigation-changed-iframe.html";
     16            });
    1517        }
    1618    </script>
  • branches/safari-607-branch/LayoutTests/http/tests/security/resources/xss-DENIED-window-open-parent-attacker.html

    r91152 r245346  
    11<script>
    2 open("javascript:alert('failed')", "_top");
    3 parent.postMessage("", "*");
     2internals.withUserGesture(() => {
     3    open("javascript:alert('failed')", "_top");
     4    parent.postMessage("", "*");
     5});
    46</script>
  • branches/safari-607-branch/LayoutTests/http/tests/security/xss-DENIED-window-open-parent-expected.txt

    r178527 r245346  
    1 CONSOLE MESSAGE: line 2: Blocked a frame with origin "http://localhost:8080" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
     1CONSOLE MESSAGE: line 3: Blocked a frame with origin "http://localhost:8080" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
    22This test passes if there is no alert dialog.
    33
  • branches/safari-607-branch/Source/WebCore/ChangeLog

    r244804 r245346  
     12019-05-14  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Cherry-pick r239742. rdar://problem/50753925
     4
     5    Prevent cross-site top-level navigations from third-party iframes
     6    https://bugs.webkit.org/show_bug.cgi?id=193076
     7    <rdar://problem/36074736>
     8   
     9    Reviewed by Alex Christensen.
     10   
     11    Source/WebCore:
     12   
     13    Prevent cross-site top-level navigations from third-party iframes if the following conditions are met:
     14    1. Its tries to navigate the top-level page cross-site (different eTDL+1)
     15    2. The user has never interacted with the third-party iframe or any of its subframes
     16   
     17    This experiment's intent is to block suspicious main-frame navigations by third-party content. The feature
     18    is behind a runtime experimental feature flag, on by default.
     19   
     20    Tests: http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html
     21           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html
     22           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html
     23           http/tests/security/block-top-level-navigations-by-third-party-iframes.html
     24   
     25    * dom/Document.cpp:
     26    (WebCore::printNavigationErrorMessage):
     27    (WebCore::Document::canNavigate):
     28    (WebCore::Document::canNavigateInternal):
     29    (WebCore::Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking):
     30    * dom/Document.h:
     31    * dom/UserGestureIndicator.cpp:
     32    * page/DOMWindow.cpp:
     33    (WebCore::DOMWindow::setLocation):
     34    * page/DOMWindow.h:
     35    * page/Frame.h:
     36    * page/Location.cpp:
     37    (WebCore::Location::replace):
     38    (WebCore::Location::setLocation):
     39    * page/Settings.yaml:
     40   
     41    Source/WebKit:
     42   
     43    Add experimental feature flag, on by default.
     44   
     45    * Shared/WebPreferences.yaml:
     46   
     47    LayoutTests:
     48   
     49    Add layout test coverage.
     50   
     51    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin-expected.txt: Added.
     52    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html: Added.
     53    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation-expected.txt: Added.
     54    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html: Added.
     55    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation-expected.txt: Added.
     56    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html: Added.
     57    * http/tests/security/block-top-level-navigations-by-third-party-iframes-expected.txt: Added.
     58    * http/tests/security/block-top-level-navigations-by-third-party-iframes.html: Added.
     59    * http/tests/security/resources/navigate-top-level-frame-to-failure-page.html: Added.
     60    * http/tests/security/resources/navigate-top-level-frame-to-success-page-same-origin.html: Added.
     61    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-previous-user-gesture.html: Added.
     62    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-user-gesture.html: Added.
     63    * http/tests/security/resources/should-have-loaded.html: Added.
     64    * http/tests/security/resources/should-not-have-loaded.html: Added.
     65   
     66   
     67    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239742 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     68
     69    2019-01-08  Chris Dumez  <cdumez@apple.com>
     70
     71            Prevent cross-site top-level navigations from third-party iframes
     72            https://bugs.webkit.org/show_bug.cgi?id=193076
     73            <rdar://problem/36074736>
     74
     75            Reviewed by Alex Christensen.
     76
     77            Prevent cross-site top-level navigations from third-party iframes if the following conditions are met:
     78            1. Its tries to navigate the top-level page cross-site (different eTDL+1)
     79            2. The user has never interacted with the third-party iframe or any of its subframes
     80
     81            This experiment's intent is to block suspicious main-frame navigations by third-party content. The feature
     82            is behind a runtime experimental feature flag, on by default.
     83
     84            Tests: http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html
     85                   http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html
     86                   http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html
     87                   http/tests/security/block-top-level-navigations-by-third-party-iframes.html
     88
     89            * dom/Document.cpp:
     90            (WebCore::printNavigationErrorMessage):
     91            (WebCore::Document::canNavigate):
     92            (WebCore::Document::canNavigateInternal):
     93            (WebCore::Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking):
     94            * dom/Document.h:
     95            * dom/UserGestureIndicator.cpp:
     96            * page/DOMWindow.cpp:
     97            (WebCore::DOMWindow::setLocation):
     98            * page/DOMWindow.h:
     99            * page/Frame.h:
     100            * page/Location.cpp:
     101            (WebCore::Location::replace):
     102            (WebCore::Location::setLocation):
     103            * page/Settings.yaml:
     104
    11052019-04-30  Alan Coon  <alancoon@apple.com>
    2106
  • branches/safari-607-branch/Source/WebCore/dom/Document.cpp

    r243592 r245346  
    457457}
    458458
    459 static void printNavigationErrorMessage(Frame* frame, const URL& activeURL, const char* reason)
    460 {
    461     String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame->document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
     459static void printNavigationErrorMessage(Frame& frame, const URL& activeURL, const char* reason)
     460{
     461    String message = "Unsafe JavaScript attempt to initiate navigation for frame with URL '" + frame.document()->url().string() + "' from frame with URL '" + activeURL.string() + "'. " + reason + "\n";
    462462
    463463    // FIXME: should we print to the console of the document performing the navigation instead?
    464     frame->document()->domWindow()->printErrorMessage(message);
     464    frame.document()->domWindow()->printErrorMessage(message);
    465465}
    466466
     
    33453345}
    33463346   
    3347 bool Document::canNavigate(Frame* targetFrame)
     3347bool Document::canNavigate(Frame* targetFrame, const URL& destinationURL)
    33483348{
    33493349    if (!m_frame)
     
    33563356        return true;
    33573357
     3358    if (!canNavigateInternal(*targetFrame))
     3359        return false;
     3360
     3361    if (isNavigationBlockedByThirdPartyIFrameRedirectBlocking(*targetFrame, destinationURL)) {
     3362        printNavigationErrorMessage(*targetFrame, url(), "The frame attempting navigation of the top-level window is cross-origin and the user has never interacted with the frame."_s);
     3363        return false;
     3364    }
     3365
     3366    return true;
     3367}
     3368
     3369bool Document::canNavigateInternal(Frame& targetFrame)
     3370{
     3371    ASSERT(m_frame);
     3372
    33583373    // Cases (i), (ii) and (iii) pass the tests from the specifications but might not pass the "security origin" tests.
    33593374
    33603375    // i. A frame can navigate its top ancestor when its 'allow-top-navigation' flag is set (sometimes known as 'frame-busting').
    3361     if (!isSandboxed(SandboxTopNavigation) && targetFrame == &m_frame->tree().top())
     3376    if (!isSandboxed(SandboxTopNavigation) && &targetFrame == &m_frame->tree().top())
    33623377        return true;
    33633378
    33643379    // ii. A frame can navigate its top ancestor when its 'allow-top-navigation-by-user-activation' flag is set and navigation is triggered by user activation.
    3365     if (!isSandboxed(SandboxTopNavigationByUserActivation) && UserGestureIndicator::processingUserGesture() && targetFrame == &m_frame->tree().top())
     3380    if (!isSandboxed(SandboxTopNavigationByUserActivation) && UserGestureIndicator::processingUserGesture() && &targetFrame == &m_frame->tree().top())
    33663381        return true;
    33673382
    33683383    // iii. A sandboxed frame can always navigate its descendants.
    3369     if (isSandboxed(SandboxNavigation) && targetFrame->tree().isDescendantOf(m_frame))
     3384    if (isSandboxed(SandboxNavigation) && targetFrame.tree().isDescendantOf(m_frame))
    33703385        return true;
    33713386
     
    33733388    // 1. If A is not the same browsing context as B, and A is not one of the ancestor browsing contexts of B, and B is not a top-level browsing context, and A's active document's active sandboxing
    33743389    // flag set has its sandboxed navigation browsing context flag set, then abort these steps negatively.
    3375     if (m_frame != targetFrame && isSandboxed(SandboxNavigation) && targetFrame->tree().parent() && !targetFrame->tree().isDescendantOf(m_frame)) {
     3390    if (m_frame != &targetFrame && isSandboxed(SandboxNavigation) && targetFrame.tree().parent() && !targetFrame.tree().isDescendantOf(m_frame)) {
    33763391        printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors."_s);
    33773392        return false;
     
    33793394
    33803395    // 2. Otherwise, if B is a top-level browsing context, and is one of the ancestor browsing contexts of A, then:
    3381     if (m_frame != targetFrame && targetFrame == &m_frame->tree().top()) {
     3396    if (m_frame != &targetFrame && &targetFrame == &m_frame->tree().top()) {
    33823397        bool triggeredByUserActivation = UserGestureIndicator::processingUserGesture();
    33833398        // 1. If this algorithm is triggered by user activation and A's active document's active sandboxing flag set has its sandboxed top-level navigation with user activation browsing context flag set, then abort these steps negatively.
     
    33953410    // 3. Otherwise, if B is a top-level browsing context, and is neither A nor one of the ancestor browsing contexts of A, and A's Document's active sandboxing flag set has its
    33963411    // sandboxed navigation browsing context flag set, and A is not the one permitted sandboxed navigator of B, then abort these steps negatively.
    3397     if (!targetFrame->tree().parent() && m_frame != targetFrame && targetFrame != &m_frame->tree().top() && isSandboxed(SandboxNavigation) && targetFrame->loader().opener() != m_frame) {
     3412    if (!targetFrame.tree().parent() && m_frame != &targetFrame && &targetFrame != &m_frame->tree().top() && isSandboxed(SandboxNavigation) && targetFrame.loader().opener() != m_frame) {
    33983413        printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is sandboxed, and is not allowed to navigate this popup."_s);
    33993414        return false;
     
    34093424    // See http://www.adambarth.com/papers/2008/barth-jackson-mitchell.pdf for
    34103425    // historical information about this security check.
    3411     if (canAccessAncestor(securityOrigin(), targetFrame))
     3426    if (canAccessAncestor(securityOrigin(), &targetFrame))
    34123427        return true;
    34133428
     
    34233438    // and/or "parent" relation). Requiring some sort of relation prevents a
    34243439    // document from navigating arbitrary, unrelated top-level frames.
    3425     if (!targetFrame->tree().parent()) {
    3426         if (targetFrame == m_frame->loader().opener())
     3440    if (!targetFrame.tree().parent()) {
     3441        if (&targetFrame == m_frame->loader().opener())
    34273442            return true;
    34283443
    3429         if (canAccessAncestor(securityOrigin(), targetFrame->loader().opener()))
     3444        if (canAccessAncestor(securityOrigin(), targetFrame.loader().opener()))
    34303445            return true;
    34313446    }
     
    34333448    printNavigationErrorMessage(targetFrame, url(), "The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener.");
    34343449    return false;
     3450}
     3451
     3452// Prevent cross-site top-level redirects from third-party iframes unless the user has ever interacted with the frame.
     3453bool Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking(Frame& targetFrame, const URL& destinationURL)
     3454{
     3455    if (!settings().thirdPartyIframeRedirectBlockingEnabled())
     3456        return false;
     3457
     3458    // Only prevent top frame navigations by subframes.
     3459    if (m_frame == &targetFrame || &targetFrame != &m_frame->tree().top())
     3460        return false;
     3461
     3462    // Only prevent navigations by subframes that the user has not interacted with.
     3463    if (m_frame->hasHadUserInteraction())
     3464        return false;
     3465
     3466    // Only prevent navigations by unsandboxed iframes. Such navigations by unsandboxed iframes would have already been blocked unless
     3467    // "allow-top-navigation" / "allow-top-navigation-by-user-activation" was explicitly specified.
     3468    if (sandboxFlags() != SandboxNone)
     3469        return false;
     3470
     3471    // Only prevent navigations by third-party iframes.
     3472    if (canAccessAncestor(securityOrigin(), &targetFrame))
     3473        return false;
     3474
     3475    // Only prevent cross-site navigations.
     3476    auto* targetDocument = targetFrame.document();
     3477    if (targetDocument && (targetDocument->securityOrigin().canAccess(SecurityOrigin::create(destinationURL)) || registrableDomainsAreEqual(targetDocument->url(), destinationURL)))
     3478        return false;
     3479
     3480    return true;
    34353481}
    34363482
  • branches/safari-607-branch/Source/WebCore/dom/Document.h

    r243592 r245346  
    708708    SocketProvider* socketProvider() final;
    709709
    710     bool canNavigate(Frame* targetFrame);
     710    bool canNavigate(Frame* targetFrame, const URL& destinationURL = URL());
    711711
    712712    bool usesStyleBasedEditability() const;
     
    16441644    void checkAppearanceDependentPictures();
    16451645
     1646    bool canNavigateInternal(Frame& targetFrame);
     1647    bool isNavigationBlockedByThirdPartyIFrameRedirectBlocking(Frame& targetFrame, const URL& destinationURL);
     1648
    16461649#if ENABLE(INTERSECTION_OBSERVER)
    16471650    void notifyIntersectionObserversTimerFired();
  • branches/safari-607-branch/Source/WebCore/dom/UserGestureIndicator.cpp

    r239427 r245346  
    2828
    2929#include "Document.h"
     30#include "Frame.h"
    3031#include "ResourceLoadObserver.h"
    3132#include <wtf/MainThread.h>
     
    6061            ResourceLoadObserver::shared().logUserInteractionWithReducedTimeResolution(document->topDocument());
    6162        document->topDocument().setUserDidInteractWithPage(true);
     63        if (auto* frame = document->frame()) {
     64            if (!frame->hasHadUserInteraction()) {
     65                for (; frame; frame = frame->tree().parent())
     66                    frame->setHasHadUserInteraction();
     67            }
     68        }
    6269    }
    6370}
  • branches/safari-607-branch/Source/WebCore/page/DOMWindow.cpp

    r244798 r245346  
    21402140}
    21412141
    2142 void DOMWindow::setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& urlString, SetLocationLocking locking)
     2142void DOMWindow::setLocation(DOMWindow& activeWindow, const URL& completedURL, SetLocationLocking locking)
    21432143{
    21442144    if (!isCurrentlyDisplayedInFrame())
     
    21502150
    21512151    auto* frame = this->frame();
    2152     if (!activeDocument->canNavigate(frame))
    2153         return;
    2154 
    2155     Frame* firstFrame = firstWindow.frame();
    2156     if (!firstFrame)
    2157         return;
    2158 
    2159     URL completedURL = firstFrame->document()->completeURL(urlString);
    2160     if (completedURL.isNull())
     2152    if (!activeDocument->canNavigate(frame, completedURL))
    21612153        return;
    21622154
  • branches/safari-607-branch/Source/WebCore/page/DOMWindow.h

    r242140 r245346  
    146146
    147147    Location& location();
    148     void setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& location, SetLocationLocking = LockHistoryBasedOnGestureState);
     148    void setLocation(DOMWindow& activeWindow, const URL& completedURL, SetLocationLocking = LockHistoryBasedOnGestureState);
    149149
    150150    DOMSelection* getSelection();
  • branches/safari-607-branch/Source/WebCore/page/Frame.h

    r241893 r245346  
    174174    bool documentIsBeingReplaced() const { return m_documentIsBeingReplaced; }
    175175
     176    bool hasHadUserInteraction() const { return m_hasHadUserInteraction; }
     177    void setHasHadUserInteraction() { m_hasHadUserInteraction = true; }
     178
    176179// ======== All public functions below this point are candidates to move out of Frame into another class. ========
    177180
     
    350353    unsigned m_navigationDisableCount { 0 };
    351354    unsigned m_selfOnlyRefCount { 0 };
     355    bool m_hasHadUserInteraction { false };
    352356
    353357protected:
  • branches/safari-607-branch/Source/WebCore/page/Location.cpp

    r238771 r245346  
    226226}
    227227
    228 void Location::replace(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& url)
     228void Location::replace(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& urlString)
    229229{
    230230    auto* frame = this->frame();
     
    233233    ASSERT(frame->document());
    234234    ASSERT(frame->document()->domWindow());
     235
     236    Frame* firstFrame = firstWindow.frame();
     237    if (!firstFrame || !firstFrame->document())
     238        return;
     239
     240    URL completedURL = firstFrame->document()->completeURL(urlString);
     241    // FIXME: The specification says to throw a SyntaxError if the URL is not valid.
     242    if (completedURL.isNull())
     243        return;
     244
    235245    // We call DOMWindow::setLocation directly here because replace() always operates on the current frame.
    236     frame->document()->domWindow()->setLocation(activeWindow, firstWindow, url, LockHistoryAndBackForwardList);
     246    frame->document()->domWindow()->setLocation(activeWindow, completedURL, LockHistoryAndBackForwardList);
    237247}
    238248
     
    265275}
    266276
    267 ExceptionOr<void> Location::setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& url)
     277ExceptionOr<void> Location::setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& urlString)
    268278{
    269279    auto* frame = this->frame();
    270280    ASSERT(frame);
    271     if (!activeWindow.document()->canNavigate(frame))
     281
     282    Frame* firstFrame = firstWindow.frame();
     283    if (!firstFrame || !firstFrame->document())
     284        return { };
     285
     286    URL completedURL = firstFrame->document()->completeURL(urlString);
     287    // FIXME: The specification says to throw a SyntaxError if the URL is not valid.
     288    if (completedURL.isNull())
     289        return { };
     290
     291    if (!activeWindow.document()->canNavigate(frame, completedURL))
    272292        return Exception { SecurityError };
     293
    273294    ASSERT(frame->document());
    274295    ASSERT(frame->document()->domWindow());
    275     frame->document()->domWindow()->setLocation(activeWindow, firstWindow, url);
     296    frame->document()->domWindow()->setLocation(activeWindow, completedURL);
    276297    return { };
    277298}
  • branches/safari-607-branch/Source/WebCore/page/Settings.yaml

    r239474 r245346  
    333333  initial: false
    334334
     335thirdPartyIframeRedirectBlockingEnabled:
     336  initial: true
     337
    335338cookieEnabled:
    336339  initial: true
  • branches/safari-607-branch/Source/WebCore/platform/network/ResourceRequestBase.h

    r239427 r245346  
    261261inline String toRegistrableDomain(const URL& a)
    262262{
    263     return ResourceRequestBase::partitionName(a.host().toString());
     263    auto host = a.host().toString();
     264    auto registrableDomain = ResourceRequestBase::partitionName(host);
     265    // Fall back to the host if we cannot determine the registrable domain.
     266    return registrableDomain.isEmpty() ? host : registrableDomain;
    264267}
    265268
  • branches/safari-607-branch/Source/WebKit/ChangeLog

    r244830 r245346  
     12019-05-14  Kocsen Chung  <kocsen_chung@apple.com>
     2
     3        Cherry-pick r239742. rdar://problem/50753925
     4
     5    Prevent cross-site top-level navigations from third-party iframes
     6    https://bugs.webkit.org/show_bug.cgi?id=193076
     7    <rdar://problem/36074736>
     8   
     9    Reviewed by Alex Christensen.
     10   
     11    Source/WebCore:
     12   
     13    Prevent cross-site top-level navigations from third-party iframes if the following conditions are met:
     14    1. Its tries to navigate the top-level page cross-site (different eTDL+1)
     15    2. The user has never interacted with the third-party iframe or any of its subframes
     16   
     17    This experiment's intent is to block suspicious main-frame navigations by third-party content. The feature
     18    is behind a runtime experimental feature flag, on by default.
     19   
     20    Tests: http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html
     21           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html
     22           http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html
     23           http/tests/security/block-top-level-navigations-by-third-party-iframes.html
     24   
     25    * dom/Document.cpp:
     26    (WebCore::printNavigationErrorMessage):
     27    (WebCore::Document::canNavigate):
     28    (WebCore::Document::canNavigateInternal):
     29    (WebCore::Document::isNavigationBlockedByThirdPartyIFrameRedirectBlocking):
     30    * dom/Document.h:
     31    * dom/UserGestureIndicator.cpp:
     32    * page/DOMWindow.cpp:
     33    (WebCore::DOMWindow::setLocation):
     34    * page/DOMWindow.h:
     35    * page/Frame.h:
     36    * page/Location.cpp:
     37    (WebCore::Location::replace):
     38    (WebCore::Location::setLocation):
     39    * page/Settings.yaml:
     40   
     41    Source/WebKit:
     42   
     43    Add experimental feature flag, on by default.
     44   
     45    * Shared/WebPreferences.yaml:
     46   
     47    LayoutTests:
     48   
     49    Add layout test coverage.
     50   
     51    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin-expected.txt: Added.
     52    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-to-same-origin.html: Added.
     53    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation-expected.txt: Added.
     54    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-previous-user-activation.html: Added.
     55    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation-expected.txt: Added.
     56    * http/tests/security/allow-top-level-navigations-by-third-party-iframes-with-user-activation.html: Added.
     57    * http/tests/security/block-top-level-navigations-by-third-party-iframes-expected.txt: Added.
     58    * http/tests/security/block-top-level-navigations-by-third-party-iframes.html: Added.
     59    * http/tests/security/resources/navigate-top-level-frame-to-failure-page.html: Added.
     60    * http/tests/security/resources/navigate-top-level-frame-to-success-page-same-origin.html: Added.
     61    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-previous-user-gesture.html: Added.
     62    * http/tests/security/resources/navigate-top-level-frame-to-success-page-with-user-gesture.html: Added.
     63    * http/tests/security/resources/should-have-loaded.html: Added.
     64    * http/tests/security/resources/should-not-have-loaded.html: Added.
     65   
     66   
     67    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239742 268f45cc-cd09-0410-ab3c-d52691b4dbfc
     68
     69    2019-01-08  Chris Dumez  <cdumez@apple.com>
     70
     71            Prevent cross-site top-level navigations from third-party iframes
     72            https://bugs.webkit.org/show_bug.cgi?id=193076
     73            <rdar://problem/36074736>
     74
     75            Reviewed by Alex Christensen.
     76
     77            Add experimental feature flag, on by default.
     78
     79            * Shared/WebPreferences.yaml:
     80
    1812019-04-30  Alan Coon  <alancoon@apple.com>
    282
  • branches/safari-607-branch/Source/WebKit/Shared/WebPreferences.yaml

    r242849 r245346  
    4141   humanReadableName: "Automatic HTTPS upgrade"
    4242   humanReadableDescription: "Automatic HTTPS upgrade for known supported sites"
     43
     44ThirdPartyIframeRedirectBlockingEnabled:
     45   type: bool
     46   defaultValue: true
     47   humanReadableName: "Block top-level redirects by third-party iframes"
     48   humanReadableDescription: "Block top-level redirects by third-party iframes"
     49   category: experimental
    4350
    4451JavaEnabled:
Note: See TracChangeset for help on using the changeset viewer.