Frame Buster Buster ... необходим код ошибки - PullRequest
406 голосов
/ 06 июня 2009

Допустим, вы не хотите, чтобы другие сайты "вставляли" ваш сайт в <iframe>:

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

Таким образом, вы вставляете антикадровый код JavaScript на всех фреймах:

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

Отлично! Теперь вы автоматически «перебираете» или выбрасываете любой содержащий iframe. За исключением одной маленькой проблемы.

Как выяснилось, ваш код перебора кадров может быть отключен , , как показано здесь :

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

Этот код выполняет следующие действия:

  • увеличивает счетчик каждый раз, когда браузер пытается отойти от текущей страницы, с помощью обработчика событий window.onbeforeunload
  • устанавливает таймер, который срабатывает каждую миллисекунду с помощью setInterval(), и, если он видит счетчик с приращением, меняет текущее местоположение на сервер управления атакующего
  • этот сервер обслуживает страницу с HTTP-кодом состояния 204 , что не приводит к перемещению браузера в любом месте

Мой вопрос - и это больше загадка JavaScript, чем реальная проблема - как вы можете победить разрушителя фреймов?

У меня было несколько мыслей, но в моем тестировании ничего не получалось:

  • попытка очистить событие onbeforeunload через onbeforeunload = null не дала эффекта
  • добавление alert() остановило процесс, чтобы пользователь знал, что это происходит, но никак не влияло на код; нажатие кнопки OK позволяет продолжить процесс как обычно
  • Я не могу придумать, как очистить таймер setInterval()

Я не очень-то программист на JavaScript, поэтому вот мой вызов для вас: Эй, Бастер, можешь уничтожить бастера?

Ответы [ 19 ]

5 голосов
/ 08 июля 2015

Начиная с 2015 года, вы должны использовать для этого директиву CSP2 frame-ancestors. Это реализовано через заголовок ответа HTTP.

, например

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

Конечно, еще не все браузеры поддерживают CSP2, поэтому целесообразно включить старый заголовок X-Frame-Options:

X-Frame-Options: DENY

Я бы посоветовал в любом случае включить оба варианта, иначе ваш сайт по-прежнему будет уязвим для Clickjacking атак в старых браузерах, и, конечно, вы получите нежелательные кадрирования даже без злонамеренного намерения. В наши дни большинство браузеров обновляются автоматически, однако корпоративные пользователи все еще склонны зависать от старых версий Internet Explorer по причинам совместимости с устаревшими приложениями.

4 голосов
/ 22 июля 2009

Если вы добавите предупреждение сразу после кода ошибки, тогда предупреждение остановит поток javascript и позволит странице загрузиться. Это то, что делает StackOverflow, и он вылетает из моих фреймов, даже когда я использую бастер. Это также работало с моей простой тестовой страницей. Это было проверено только в Firefox 3.5 и IE7 на Windows.

Код:

<script type="text/javascript">
if (top != self){
  top.location.replace(self.location.href);
  alert("for security reasons bla bla bla");
}
</script>
4 голосов
/ 06 июня 2009

Ну, вы можете изменить значение счетчика, но это, очевидно, хрупкое решение. Вы можете загрузить свой контент через AJAX после того, как вы определили, что сайт находится за пределами фрейма - тоже не очень хорошее решение, но мы надеемся, что оно предотвращает запуск события on beforeunload (я предполагаю).

Редактировать: еще одна идея. Если вы обнаружите, что находитесь в кадре, попросите пользователя отключить JavaScript, прежде чем щелкнуть ссылку, которая приведет вас к нужному URL-адресу (передав строку запроса, позволяющую вашей странице сообщить пользователю, что он может повторно включить JavaScript, когда они есть).

Редактировать 2: Идите ядерным путем - если вы обнаружите, что находитесь в рамке, просто удалите содержимое тела документа и напечатайте какое-нибудь неприятное сообщение.

Редактировать 3: Можете ли вы перечислить верхний документ и установить все функции на ноль (даже анонимные)?

3 голосов
/ 06 июня 2009

Я думаю, что вы были почти там. Вы пробовали:

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

или, альтернативно:

window.parent.prevent_bust = 0;

Примечание: я не проверял это на самом деле.

2 голосов
/ 06 июня 2009

А как насчет того, чтобы неоднократно вызывать бастера? Это создаст условия гонки, но можно надеяться, что бастер выйдет победителем:

(function() {
    if(top !== self) {
        top.location.href = self.location.href;
        setTimeout(arguments.callee, 0);
    }
})();
2 голосов
/ 20 февраля 2011

Возможно, я только что получил способ уничтожить javascript. Используя getElementsByName в моей функции javascript, я установил петлю между обработчиком кадров и реальным сценарием уничтожения кадров. проверить этот пост. http://www.phcityonweb.com/frame-buster-buster-buster-2426

2 голосов
/ 21 февраля 2010

Если вы посмотрите на значения, возвращаемые setInterval(), они обычно представляют собой однозначные цифры, поэтому вы можете отключить все такие прерывания одной строкой кода:

for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
0 голосов
/ 18 декабря 2013

Используйте htaccess, чтобы избежать фреймов с высоким уровнем домкрата, iframe и любого другого контента, например изображений.

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

Появится страница с информацией об авторских правах вместо ожидаемой.

0 голосов
/ 23 декабря 2009

setInterval и setTimeout создают автоматически увеличивающийся интервал. Каждый раз, когда вызывается setTimeout или setInterval, это число увеличивается на единицу, поэтому, если вы вызовете setTimeout, вы получите текущее максимальное значение.

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

Поскольку почти 10000 одновременных операций setIntervals и setTimeouts работают почти 10000, а setTimeout возвращает "последний созданный интервал или время ожидания + 1", а поскольку top.clearInterval по-прежнему доступен, это приведет к поражению черной шляпы. атаки на фрейм-сайты, описанные выше.

...