Ramka Buster Buster ... Buster kod potrzebny

Powiedzmy, że nie chcesz, aby inne witryny "oprawiały" Twoją witrynę w <iframe>:

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

Więc wstawiasz anty-framing, frame busting JavaScript na wszystkie strony:

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

Doskonale! Teraz automatycznie "biust" lub wyłamujesz się z dowolnego iframe ' a. Poza jednym małym problemem.

Jak się okazuje, Twój kod może zostać złamany, Jak pokazano tutaj :

<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>

Ten kod wykonuje następujące czynności:

  • przyrosty a licznik za każdym razem, gdy przeglądarka próbuje odsunąć się od bieżącej strony, za pomocą procedury obsługi zdarzenia window.onbeforeunload
  • ustawia timer, który uruchamia co milisekundę przez setInterval(), a jeśli widzi licznik zwiększony, zmienia bieżącą lokalizację na serwer kontroli atakującego
  • ten serwer wyświetla stronę z kodem statusu HTTP 204, co nie powoduje, że przeglądarka w dowolnym miejscu

Moje pytanie brzmi -- i to jest bardziej zagadka JavaScript niż prawdziwy problem -- jak możesz pokonać Bustera?

Miałem kilka przemyśleń, ale nic nie działało w moich testach:

  • próba oczyszczenia zdarzenia onbeforeunload przez onbeforeunload = null nie przyniosła efektu
  • dodanie alert() zatrzymało proces, dając użytkownikowi znać, że to się dzieje, ale nie zakłócało kodu w żaden sposób; kliknięcie OK pozwala na kontynuowanie pracy w trybie normalnym
  • nie mogę wymyślić żadnego sposobu, aby wyczyścić setInterval() timer

Nie jestem dużo programisty JavaScript, więc oto moje wyzwanie dla ciebie: Hej buster, możesz rozwalić Bustera?

Author: David Archer, 2009-06-06

19 answers

Nie jestem pewien, czy to jest realne, czy nie - ale jeśli nie możesz złamać ramki, dlaczego po prostu nie wyświetlić Ostrzeżenia. Na przykład, jeśli Twoja strona nie jest "top page", Utwórz metodę setInterval, która spróbuje przerwać ramkę. Jeśli po 3 lub 4 próbach Twoja strona nadal nie jest górną stroną-utwórz element div, który obejmuje całą stronę (pole modalne) z wiadomością i linkiem...

Przeglądasz tę stronę w nieautoryzowanym oknie ramki - (Bla bla... potencjalny problem bezpieczeństwa)

Kliknij ten link, aby rozwiązać ten problem

Nie najlepszy, ale nie widzę sposobu, żeby się z tego wykręcili.

 140
Author: Hugoware,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-18 13:21:16
 201
Author: EricLaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-28 17:52:18

Zastosowaliśmy następujące podejście na jednej z naszych stron internetowych z http://seclab.stanford.edu/websec/framebusting/framebust.pdf

<style>
 body { 
 display : none   
}
</style>
<script>
if(self == top) {
document.getElementsByTagName("body")[0].style.display = 'block';
}
else{
top.location = self.location;
}
</script>
 30
Author: Dungeon Hunter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-05 19:21:23

Wymyśliłem to i wydaje się działać przynajmniej w Firefoksie i przeglądarce Opera.

if(top != self) {
 top.onbeforeunload = function() {};
 top.location.replace(self.location.href);
}
 29
Author: Jani Hartikainen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-25 09:31:59

Biorąc pod uwagę obecny standard HTML5, który wprowadził sandbox dla ramki iframe, wszystkie kody burz ramek, które są dostępne na tej stronie, mogą być wyłączone, gdy atakujący używa sandboxa, ponieważ ogranicza iframe od następujących:

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
Zobacz też: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox

Rozważ, że atakujący użył następującego kodu do hostowania Twojej witryny w iframe:

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

Wtedy cała Ramka JavaScript złamanie kodu nie powiedzie się.

Po sprawdzeniu całego kodu szyny, tylko ta obrona działa we wszystkich przypadkach:

<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>

To pierwotnie zaproponowane przez Gustava Rydstedta, Elie Bursztein, dana Boneha i Collina Jacksona (2010)

 20
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 20:53:18

Po zastanowieniu się nad tym przez chwilę, wierzę, że to pokaże im, kto tu rządzi...

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

Użycie _top jako parametru docelowego dla window.open() spowoduje uruchomienie go w tym samym oknie.

 19
Author: Josh Stodola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-04 04:50:07
if (top != self) {
  top.location.replace(location);
  location.replace("about:blank"); // want me framed? no way!
}
 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 15:23:24

OK, więc wiemy, że były w kadrze. Więc mamy lokalizację.href do innej specjalnej strony ze ścieżką jako zmienną GET. Teraz wyjaśniamy użytkownikowi, co się dzieje i podajemy link z opcją target= "_TOP". Jest prosty i prawdopodobnie zadziała( nie testowałem go), ale wymaga pewnej interakcji użytkownika. Może mógłbyś zwrócić uwagę na obrażającą stronę użytkownikowi i zrobić halę wstydu dla klikaczy na Twoją stronę.. To tylko pomysł, ale praca w nocy..

 5
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-12 01:44:09

Wszystkie proponowane rozwiązania wymuszają bezpośrednio zmianę położenia górnego okna. Co jeśli użytkownik chce, aby ramka tam była? Na przykład górna ramka w wynikach zdjęć wyszukiwarek.

Napisałem prototyp, w którym domyślnie wszystkie wejścia (linki, formularze i elementy wejściowe) są wyłączone i/lub nic nie robią po aktywacji.

W przypadku wykrycia ramki zawierającej dane wejściowe są wyłączone, a na górze strony wyświetlany jest komunikat ostrzegawczy. Komunikat ostrzegawczy zawiera link, który otworzy bezpieczną wersję strony w nowym oknie. Zapobiega to używaniu strony do klikania, jednocześnie umożliwiając użytkownikowi przeglądanie zawartości w innych sytuacjach.

Jeśli nie wykryto ramki zawierającej, wejścia są włączone.

Oto kod. Musisz ustawić standardowe atrybuty HTML na bezpieczne wartości i dodać atrybuty dodatkowe, które zawierają rzeczywiste wartości. Prawdopodobnie jest niekompletny i dla pełnego bezpieczeństwa dodatkowe atrybuty (jestem thinking about event handlers) będzie prawdopodobnie musiał być traktowany w ten sam sposób:

<!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
Author: Johan Stuyts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 01:47:38

[[6]] będę odważny i wrzucę czapkę do ringu na tej (starożytnej jak to jest), zobaczyć, ile downvotów mogę zebrać.

Oto moja próba, która zdaje się działać wszędzie, gdzie ją przetestowałem (Chrome20, IE8 i 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);
}());

Umieściłem ten kod w <head> i wywołałem go od końca <body>, aby upewnić się, że moja strona jest renderowana, zanim zacznie się kłócić ze złośliwym kodem, Nie wiem, czy jest to najlepsze podejście, YMMV.

Jak to praca?

...Słyszałem, że pytasz-cóż, szczera odpowiedź jest taka, że ja naprawdę Nie wiem. Wymagało to dużo fudgingu, aby działało wszędzie, gdzie testowałem, a dokładny efekt, jaki ma, różni się nieznacznie w zależności od tego, gdzie go uruchamiasz.

Oto myśl za tym:

  • ustaw funkcję, która będzie działać w najniższym możliwym interwale. Podstawową koncepcją stojącą za którymkolwiek z realistycznych rozwiązań, które widziałem, jest wypełnienie harmonogramu większą liczbą zdarzeń niż frame buster-buster ma.
  • za każdym razem, gdy funkcja zostanie wywołana, spróbuj zmienić położenie górnej ramki. Dość oczywisty wymóg.
  • zaplanuj również natychmiastowe uruchomienie funkcji, która zajmie dużo czasu (blokując tym samym frame buster-buster przed ingerencją w zmianę lokalizacji). Wybrałem synchroniczny XMLHttpRequest, ponieważ jest to jedyny mechanizm, który nie wymaga (a przynajmniej nie wymaga) interakcji użytkownika i nie gryzie użytkownika Czas procesora.

Dla mojego http://mysite.tld/page-that-takes-a-while-to-load (cel XHR) użyłem skryptu PHP, który wygląda tak:

<?php sleep(5);

Co się dzieje?

  • Chrome i Firefox czekają 5 sekund na zakończenie XHR, a następnie pomyślnie przekierowują do adresu URL strony w ramce.
  • IE przekierowuje praktycznie od razu

Nie można uniknąć czasu oczekiwania w Chrome i Firefox?

Najwyraźniej nie. Na początku wskazałem XHR na adres URL, który zwróci a 404 - to nie działa w Firefoksie. Następnie wypróbowałem podejście sleep(5);, na które ostatecznie wylądowałem, aby uzyskać tę odpowiedź, a następnie zacząłem bawić się długością snu na różne sposoby. Nie mogłem znaleźć prawdziwego wzorca na zachowaniu, ale stwierdziłem, że jeśli jest za Krótki, to konkretnie Firefox nie będzie grał w piłkę (Chrome i IE wydają się być dość dobrze zachowywane). Nie wiem, jaka jest definicja "zbyt krótki" w kategoriach realnych, ale 5 sekund wydaje się działać za każdym razem.

Jeśli każdy przechodzący Javascript ninja chce wyjaśnić trochę lepiej, co się dzieje, dlaczego jest to (prawdopodobnie) złe, niewiarygodne, najgorszy kod, jaki kiedykolwiek widzieli itp.chętnie posłucham.

 5
Author: DaveRandom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 12:21:05

Od 2015 roku powinieneś używać CSP2 frame-ancestors dyrektywa w tej sprawie. Jest to realizowane poprzez nagłówek odpowiedzi HTTP.

Np.

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

Oczywiście niewiele przeglądarek obsługuje jeszcze CSP2, więc mądrze jest włączyć stare X-Frame-Options nagłówek:

X-Frame-Options: DENY

Radzę i tak dołączyć oba, w przeciwnym razie twoja strona będzie nadal podatna na ataki Clickjacking w starych przeglądarkach i oczywiście dostaniesz niepożądane kadrowanie nawet bez złośliwego intencja. Większość przeglądarek aktualizuje się automatycznie w dzisiejszych czasach, jednak nadal masz tendencję do uzyskania użytkowników korporacyjnych utknęło na starych wersjach programu Internet Explorer ze względu na kompatybilność starszych aplikacji.

 5
Author: SilverlightFox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-08 09:01:01

Cóż, można zmodyfikować wartość licznika, ale to oczywiście kruche rozwiązanie. Możesz załadować treść za pośrednictwem AJAX po ustaleniu, że witryna nie jest w ramce - również nie jest to świetne rozwiązanie ,ale mam nadzieję, że unika odpalenia przed wydarzeniem unload(zakładam).

Edit: kolejny pomysł. Jeśli zauważysz, że jesteś w ramce, Poproś użytkownika o wyłączenie obsługi javascript, zanim klikniesz link, który przeniesie Cię do żądanego adresu URL (przekazując querystring, który pozwala twojej stronie wiedzieć, aby powiedzieć użytkownikowi, że może ponownie włączyć javascript, gdy już tam są).

Edit 2: Go nuclear-jeśli zauważysz, że jesteś w ramce, po prostu usuń treść dokumentu i wydrukuj paskudną wiadomość.

Edit 3: Czy możesz wyliczyć górny dokument i ustawić wszystkie funkcje na null (nawet te anonimowe)?

 4
Author: RedFilter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 04:51:54

Jeśli dodasz alert zaraz po kodzie Bustera, alert zatrzyma wątek javascript i pozwoli załadować stronę. To właśnie robi StackOverflow i wypiera z moich ramek iFrame, nawet gdy używam ramki Buster. Działał również z moją prostą stroną testową. Zostało to Przetestowane tylko w Firefoksie 3.5 i IE7 w systemie windows.

Kod:

<script type="text/javascript">
if (top != self){
  top.location.replace(self.location.href);
  alert("for security reasons bla bla bla");
}
</script>
 4
Author: Marius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-22 09:17:09

Myślę, że byłeś prawie na miejscu. Próbowałeś:

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

Lub alternatywnie:

window.parent.prevent_bust = 0;

Uwaga: nie testowałem tego.

 3
Author: Jeff Meatball Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 04:56:50

A co z wielokrotnym wydzwanianiem do Bustera? To stworzy warunki rasowe, ale można mieć nadzieję, że buster wyjdzie na szczyt: {]}

(function() {
    if(top !== self) {
        top.location.href = self.location.href;
        setTimeout(arguments.callee, 0);
    }
})();
 2
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 09:20:33

Jeśli spojrzysz na wartości zwracane przez setInterval() są to zwykle pojedyncze cyfry, więc możesz Zwykle wyłączyć wszystkie takie przerwania za pomocą jednej linii kodu:

for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
 2
Author: Robin Nixon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-21 17:39:25

Właśnie znalazłem sposób na rozwalenie frame buster Buster javascript. Korzystając z getElementsByName w mojej funkcji javascript, ustawiłem pętlę między frame buster a rzeczywistym skryptem frame buster buster. sprawdź ten post. http://www.phcityonweb.com/frame-buster-buster-buster-2426

 2
Author: Phcityonweb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-20 14:42:48

SetInterval i setTimeout tworzą automatycznie zwiększający się interwał. Przy każdym wywołaniu setTimeout lub setInterval, liczba ta wzrasta o jeden, więc jeśli wywołasz setTimeout, otrzymasz aktualną, najwyższą wartość.

   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";
   }

Ponieważ jest prawie niespotykane, aby działało 10000 jednoczesnych interwałów i settimeoutów, a ponieważ setTimeout zwraca "last interval or timeout created + 1", a od top.clearInterval jest nadal dostępny, to pokona black-hat ataki na strony internetowe, które zostały opisane powyżej.

 0
Author: cwallenpoole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 15:40:15

Użyj htaccess, aby uniknąć wysokiej jakości frameset, iframe i wszelkich treści, takich jak obrazy.

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

Wyświetli stronę praw autorskich zamiast oczekiwanej.

 0
Author: B.F.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 19:14:53