it-swarm.com.de

Frame Buster Buster ... Buster-Code benötigt

Angenommen, Sie möchten nicht, dass andere Websites Ihre Website in einem <iframe> "Rahmen":

<iframe src="http://example.org"></iframe>

So fügen Sie Anti-Framing, Frame Busting JavaScript in alle Ihre Seiten ein:

/* break us out of any containing iframes */
if (top != self) { top.location.replace(self.location.href); }

Ausgezeichnet! Jetzt können Sie automatisch aus allen enthaltenen Iframes "ausbrechen" oder ausbrechen. Bis auf ein kleines Problem.

Wie sich herausstellt, kann Ihr Frame-Busting-Code gesprengt werden , wie hier gezeigt :

<script type="text/javascript">
    var prevent_bust = 0  
    window.onbeforeunload = function() { prevent_bust++ }  
    setInterval(function() {  
      if (prevent_bust > 0) {  
        prevent_bust -= 2  
        window.top.location = 'http://example.org/page-which-responds-with-204'  
      }  
    }, 1)  
</script>

Dieser Code bewirkt Folgendes:

  • inkrementiert einen Zähler jedes Mal, wenn der Browser versucht, über die Ereignisbehandlungsroutine window.onbeforeunload von der aktuellen Seite weg zu navigieren
  • richtet einen Timer ein, der jede Millisekunde über setInterval() ausgelöst wird. Wenn der Zähler inkrementiert wird, wird der aktuelle Standort in einen Server geändert, der der Kontrolle des Angreifers unterliegt
  • dieser Server stellt eine Seite mit dem HTTP-Statuscode 204 bereit, die den Browser nicht dazu veranlasst, irgendwohin zu navigieren

Meine Frage ist - und dies ist eher ein JavaScript-Puzzle als ein tatsächliches Problem - wie können Sie den Frame-Busting-Buster besiegen?

Ich hatte ein paar Gedanken, aber bei meinen Tests hat nichts funktioniert:

  • der Versuch, das Ereignis onbeforeunload über onbeforeunload = null zu löschen, hatte keine Auswirkung
  • das Hinzufügen einer alert() hat den Prozess gestoppt und den Benutzer darüber informiert, dass dies geschehen ist, ohne jedoch den Code in irgendeiner Weise zu beeinträchtigen; Wenn Sie auf OK klicken, wird das Busting wie gewohnt fortgesetzt
  • Ich kann mir keine Möglichkeit vorstellen, den Timer setInterval() zu löschen

Ich bin kein großer JavaScript-Programmierer, also hier ist meine Herausforderung für Sie: Hey Buster, können Sie den Frame-Busting-Buster kaputt machen?

408
Jeff Atwood

Ich bin mir nicht sicher, ob dies machbar ist oder nicht - aber wenn Sie den Rahmen nicht brechen können, zeigen Sie einfach eine Warnung an. Wenn Ihre Seite beispielsweise nicht die "Startseite" ist, erstellen Sie eine setInterval-Methode, die versucht, den Frame zu unterbrechen. Wenn Ihre Seite nach 3 oder 4 Versuchen immer noch nicht die oberste Seite ist - erstellen Sie ein div-Element, das die gesamte Seite (Modal Box) mit einer Meldung und einem Link wie ...

Sie sehen diese Seite in einem nicht autorisierten Frame-Fenster Blah blah ... potenzielles Sicherheitsproblem)

--- (Klicken Sie auf diesen Link, um dieses Problem zu beheben

Nicht die besten, aber ich sehe keine Möglichkeit, wie sie sich daraus herausarbeiten könnten.

146
Hugoware
205
EricLaw

Wir haben den folgenden Ansatz in einer unserer Websites von http://seclab.stanford.edu/websec/framebusting/framebust.pdf verwendet

<style>
 body { 
 display : none   
}
</style>
<script>
if(self == top) {
document.getElementsByTagName("body")[0].style.display = 'block';
}
else{
top.location = self.location;
}
</script>
33
Dungeon Hunter

Kam damit klar, und es scheint zumindest in Firefox und dem Opera Browser zu funktionieren.

if(top != self) {
 top.onbeforeunload = function() {};
 top.location.replace(self.location.href);
}
29

In Anbetracht des aktuellen HTML5-Standards, der Sandbox für Iframe eingeführt hat, können alle auf dieser Seite bereitgestellten Frame-Busting-Codes deaktiviert werden, wenn der Angreifer Sandbox verwendet, da dies den Iframe von Folgendem einschränkt:

allow-forms: Allow form submissions.
allow-popups: Allow opening popup windows.
allow-pointer-lock: Allow access to pointer movement and pointer lock.
allow-same-Origin: Allow access to DOM objects when the iframe loaded form same Origin
allow-scripts: Allow executing scripts inside iframe
allow-top-navigation: Allow navigation to top level window

Bitte beachten Sie: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox

Angenommen, der Angreifer hat den folgenden Code zum Hosten Ihrer Website in iframe verwendet:

<iframe src="URI" sandbox></iframe>

Dann schlägt der gesamte JavaScript-Frame-Busting-Code fehl.

Nach Überprüfung des gesamten Frame-Busing-Codes funktioniert nur diese Verteidigung in allen Fällen:

<style id="antiClickjack">body{display:none !important;}</style>
<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

das ursprünglich vorgeschlagen von Gustav Rydstedt, Elie Bursztein, Dan Boneh und Collin Jackson (2010)

23
user1646111

Nachdem ich eine Weile darüber nachgedacht habe, glaube ich, dass dies ihnen zeigen wird, wer der Boss ist ...

if(top != self) {
  window.open(location.href, '_top');
}

Wenn Sie _top Als Zielparameter für window.open() verwenden, wird es im selben Fenster gestartet.

19
Josh Stodola
if (top != self) {
  top.location.replace(location);
  location.replace("about:blank"); // want me framed? no way!
}
6
Giorgio Maone

Ok, wir wissen also, dass das in einem Frame war. Also müssen wir location.href zu einer anderen speziellen Seite mit dem Pfad als GET-Variable. Wir erklären dem Benutzer nun, was los ist und stellen einen Link mit der Option target = "_ TOP" bereit. Es ist einfach und würde wahrscheinlich funktionieren (habe es nicht getestet), aber es erfordert einige Benutzerinteraktion. Vielleicht könnten Sie den Benutzer auf die störende Site aufmerksam machen und die Clickjacker zu einer Schande für Ihre Site machen. Nur eine Idee, aber es funktioniert nachts.

5
Mike

Ich werde mutig sein und meinen Hut in den Ring werfen, um zu sehen, wie viele Downvotes ich sammeln kann.

Hier ist mein Versuch, der anscheinend überall funktioniert, wo ich ihn getestet habe (Chrome20, IE8 und FF14):

(function() {
    if (top == self) {
        return;
    }

    setInterval(function() {
        top.location.replace(document.location);
        setTimeout(function() {
            var xhr = new XMLHttpRequest();
            xhr.open(
                'get',
                'http://mysite.tld/page-that-takes-a-while-to-load',
                false
            );
            xhr.send(null);
        }, 0);
    }, 1);
}());

Ich habe diesen Code in den <head> Eingegeben und ihn am Ende des <body> Aufgerufen, um sicherzustellen, dass meine Seite gerendert wird, bevor sie mit dem bösartigen Code zu streiten beginnt. Ich weiß nicht, ob dies der beste ist Ansatz, YMMV.

Wie funktioniert es?

... Ich höre Sie fragen - nun ja, die ehrliche Antwort lautet, ich weiß nicht wirklich. Es hat eine Menge Unsinn gekostet, damit es überall funktioniert, wo ich es getestet habe, und der genaue Effekt, den es hat, variiert geringfügig, je nachdem, wo Sie es ausführen.

Hier ist das Denken dahinter:

  • Stellen Sie eine Funktion so ein, dass sie im niedrigstmöglichen Intervall ausgeführt wird. Das Grundkonzept hinter jeder der realistischen Lösungen, die ich gesehen habe, besteht darin, den Scheduler mit mehr Ereignissen zu füllen, als der Frame-Buster-Buster hat.
  • Versuchen Sie bei jedem Auslösen der Funktion, die Position des oberen Rahmens zu ändern. Ziemlich offensichtliche Anforderung.
  • Planen Sie außerdem ein, dass eine Funktion sofort ausgeführt wird, was lange dauern wird (wodurch der Frame-Buster-Buster daran gehindert wird, den Standortwechsel zu stören). Ich habe eine synchrone XMLHttpRequest gewählt, da dies der einzige Mechanismus ist, der meiner Meinung nach keine Benutzerinteraktion erfordert (oder zumindest verlangt) und die CPU-Zeit des Benutzers nicht belastet.

Für meinen http://mysite.tld/page-that-takes-a-while-to-load (Das Ziel der XHR) habe ich ein PHP= Skript verwendet, das so aussieht:

<?php sleep(5);

Was passiert?

  • Chrome und Firefox warten die 5 Sekunden, bis der XHR-Vorgang abgeschlossen ist, und leiten dann erfolgreich zur URL der umrahmten Seite weiter.
  • IE leitet ziemlich sofort weiter

Können Sie nicht die Wartezeit in Chrome und Firefox? vermeiden

Scheinbar nicht. Zuerst habe ich die XHR auf eine URL verwiesen, die eine 404 zurückgeben würde - dies funktionierte in Firefox nicht. Dann habe ich den sleep(5); -Ansatz ausprobiert, auf den ich schließlich für diese Antwort gestoßen bin, und dann habe ich auf verschiedene Arten angefangen, mit der Schlafdauer herumzuspielen. Ich konnte kein echtes Muster für das Verhalten finden, aber ich habe festgestellt, dass, wenn es zu kurz ist, Firefox nicht zum Ballspiel wird (Chrome und IE scheinen sich ziemlich gut zu benehmen). Ich ziehe an weiß nicht, was die Definition von "zu kurz" ist, aber 5 Sekunden scheint jedes Mal zu arbeiten.


Wenn ein passierender Javascript-Ninjas etwas besser erklären möchte, was los ist, warum dies (wahrscheinlich) falsch, unzuverlässig, der schlechteste Code ist, den er je gesehen hat, usw. Ich werde glücklich zuhören.

5
DaveRandom

Alle vorgeschlagenen Lösungen erzwingen direkt eine Änderung der Position des oberen Fensters. Was ist, wenn ein Benutzer den Rahmen dort haben möchte? Zum Beispiel der obere Frame in den Bildergebnissen von Suchmaschinen.

Ich habe einen Prototyp geschrieben, bei dem standardmäßig alle Eingaben (Links, Formulare und Eingabeelemente) deaktiviert sind und/oder nichts tun, wenn sie aktiviert sind.

Wenn ein umhüllender Frame erkannt wird, bleiben die Eingaben deaktiviert, und oben auf der Seite wird eine Warnmeldung angezeigt. Die Warnmeldung enthält einen Link, der eine sichere Version der Seite in einem neuen Fenster öffnet. Auf diese Weise wird verhindert, dass die Seite für Clickjacking verwendet wird, und der Benutzer kann den Inhalt auch in anderen Situationen anzeigen.

Wenn kein enthaltender Frame erkannt wird, werden die Eingänge aktiviert.

Hier ist der Code. Sie müssen die Standard-HTML-Attribute auf sichere Werte setzen und zusätzliche Attribute hinzufügen, die die tatsächlichen Werte enthalten. Es ist wahrscheinlich unvollständig und aus Sicherheitsgründen müssen zusätzliche Attribute (ich denke an Event-Handler) wahrscheinlich auf die gleiche Weise behandelt werden:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
  <head>
    <title></title>
    <script><!--
      function replaceAttributeValuesWithActualOnes( array, attributeName, actualValueAttributeName, additionalProcessor ) {
        for ( var elementIndex = 0; elementIndex < array.length; elementIndex += 1 ) {
          var element = array[ elementIndex ];
          var actualValue = element.getAttribute( actualValueAttributeName );
          if ( actualValue != null ) {
            element[ attributeName ] = actualValue;
          }

          if ( additionalProcessor != null ) {
            additionalProcessor( element );
          }
        }
      }

      function detectFraming() {
        if ( top != self ) {
          document.getElementById( "framingWarning" ).style.display = "block";
        } else {
          replaceAttributeValuesWithActualOnes( document.links, "href", "acme:href" );

          replaceAttributeValuesWithActualOnes( document.forms, "action", "acme:action", function ( form ) {
            replaceAttributeValuesWithActualOnes( form.elements, "disabled", "acme:disabled" );
          });
        }
      }
      // -->
    </script>
  </head>
  <body onload="detectFraming()">
    <div id="framingWarning" style="display: none; border-style: solid; border-width: 4px; border-color: #F00; padding: 6px; background-color: #FFF; color: #F00;">
      <div>
        <b>SECURITY WARNING</b>: Acme App is displayed inside another page.
        To make sure your data is safe this page has been disabled.<br>
        <a href="framing-detection.html" target="_blank" style="color: #090">Continue working safely in a new tab/window</a>
      </div>
    </div>
    <p>
      Content. <a href="#" acme:href="javascript:window.alert( 'Action performed' );">Do something</a>
    </p>
    <form name="acmeForm" action="#" acme:action="real-action.html">
      <p>Name: <input type="text" name="name" value="" disabled="disabled" acme:disabled=""></p>
      <p><input type="submit" name="save" value="Save" disabled="disabled" acme:disabled=""></p>
    </form>
  </body>
</html>
5
Johan Stuyts

Ab 2015 sollten Sie CSP2s frame-ancestors Anweisung dafür. Dies wird über einen HTTP-Antwortheader implementiert.

z.B.

Content-Security-Policy: frame-ancestors 'none'

Natürlich unterstützen noch nicht viele Browser CSP2, daher ist es ratsam, das alte X-Frame-Options header:

X-Frame-Options: DENY

Ich würde sowieso empfehlen, beides einzuschließen, da Ihre Site sonst weiterhin anfällig für Clickjacking Angriffe in alten Browsern ist und Sie natürlich auch ohne böswillige Absicht unerwünschte Frames erhalten würden. Die meisten Browser werden heutzutage automatisch aktualisiert. Aus Gründen der Kompatibilität mit älteren Anwendungen stecken jedoch häufig Unternehmensbenutzer in alten Versionen von Internet Explorer fest.

5
SilverlightFox

Wenn Sie eine Warnung direkt nach dem Buster-Code hinzufügen, wird der JavaScript-Thread durch die Warnung blockiert und die Seite wird geladen. Dies ist, was StackOverflow macht, und es springt aus meinen iframes heraus, selbst wenn ich den Frame-Busting-Buster verwende. Es funktionierte auch mit meiner einfachen Testseite. Dies wurde nur in Firefox 3.5 und IE7 unter Windows getestet.

Code:

<script type="text/javascript">
if (top != self){
  top.location.replace(self.location.href);
  alert("for security reasons bla bla bla");
}
</script>
4
Marius

Nun, Sie können den Wert des Zählers ändern, aber das ist offensichtlich eine spröde Lösung. Sie können Ihren Inhalt über AJAX) laden, nachdem Sie festgestellt haben, dass sich die Site nicht innerhalb eines Frames befindet - auch keine gute Lösung, aber es wird hoffentlich vermieden, das Ereignis on before unload auszulösen (nehme ich an).

Edit: Eine andere Idee. Wenn Sie feststellen, dass Sie sich in einem Frame befinden, bitten Sie den Benutzer, Javascript zu deaktivieren, bevor Sie auf einen Link klicken, der Sie zur gewünschten URL führt gibt es).

Bearbeiten 2: Nuklear werden - Wenn Sie feststellen, dass Sie sich in einem Frame befinden, löschen Sie einfach den Inhalt Ihres Dokuments und drucken Sie eine böse Nachricht aus.

Edit 3: Können Sie das oberste Dokument auflisten und alle Funktionen auf Null setzen (auch anonyme)?

4
RedFilter

Ich glaube du warst fast da. Hast du es versucht:

window.parent.onbeforeunload = null;
window.parent.location.replace(self.location.href);

oder alternativ:

window.parent.prevent_bust = 0;

Hinweis: Ich habe das nicht getestet.

3

Wenn Sie sich die von setInterval() zurückgegebenen Werte ansehen, handelt es sich in der Regel um einzelne Ziffern. Daher können Sie diese Interrupts in der Regel mit einer einzigen Codezeile deaktivieren:

for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
2
Robin Nixon

Was ist, wenn Sie den Buster auch wiederholt anrufen? Dies schafft eine Rennbedingung, aber man kann hoffen, dass der Buster die Nase vorn hat:

(function() {
    if(top !== self) {
        top.location.href = self.location.href;
        setTimeout(arguments.callee, 0);
    }
})();
2
Christoph

Ich könnte gerade eine Möglichkeit bekommen haben, das Frame-Buster-Buster-Javascript zu sprengen. Mit dem getElementsByName in meiner Javascript-Funktion habe ich eine Schleife zwischen dem Frame-Buster und dem eigentlichen Frame-Buster-Buster-Skript gesetzt. schau dir diesen Beitrag an. http://www.phcityonweb.com/frame-buster-buster-buster-2426

2
Phcityonweb

Verwenden Sie htaccess, um zu vermeiden, dass Framesets, Iframes und andere Inhalte wie Bilder überlastet werden.

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://www\.yoursite\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule ^(.*)$ /copyrights.html [L]

Dies zeigt eine Copyright-Seite anstelle der erwarteten.

0
B.F.

setInterval und setTimeout erstellen ein automatisch inkrementierendes Intervall. Bei jedem Aufruf von setTimeout oder setInterval wird diese Zahl um eins erhöht, sodass Sie beim Aufrufen von setTimeout den aktuellen, höchsten Wert erhalten.

   var currentInterval = 10000;
   currentInterval += setTimeout( gotoHREF, 100 );
   for( var i = 0; i < currentInterval; i++ ) top.clearInterval( i );
   // Include setTimeout to avoid recursive functions.
   for( i = 0; i < currentInterval; i++ )     top.clearTimeout( i );

   function gotoHREF(){
           top.location.href = "http://your.url.here";
   }

Da es so gut wie unbekannt ist, dass 10000 setIntervals und setTimeouts gleichzeitig aktiv sind und setTimeout "zuletzt erstelltes Intervall oder Timeout + 1" zurückgibt und auf top.clearInterval weiterhin zugegriffen werden kann, werden die Black-Hat-Angriffe auf Frames verhindert Websites, die oben beschrieben sind.

0
cwallenpoole