Кадр Бастер Бастер ... нужен код Бастера
допустим, вы не хотите, чтобы другие сайты "обрамляли" ваш сайт в <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, чем фактическая
19 ответов:
Я не уверен, что это жизнеспособно или нет - но если вы не можете сломать кадр, почему бы просто не отобразить предупреждение. Например, если ваша страница не является "верхней страницей", создайте метод setInterval, который пытается разорвать фрейм. Если после 3 или 4 попыток ваша страница все еще не топ-страницы - создать элемент div, который охватывает всю страницу (модальное окно) с сообщение и ссылку...
вы просматриваете эту страницу в окне несанкционированного фрейма - (бла-бла... потенциальная безопасность выпуск)
нажмите на эту ссылку, чтобы исправить эту проблему
Не самый лучший, но я не вижу никакого способа, которым они могли бы написать свой выход из этого.
FWIW, большинство современных браузеров поддержка the X-Frame-Options: deny директива, которая работает даже при отключенном скрипте.
IE8:
http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspxFirefox (3.6.9)
https://bugzilla.mozilla.org/show_bug.cgi?id=475530
https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_headerChrome/Webkit
http://blog.chromium.org/2010/01/security-in-depth-new-security-features.html
http://trac.webkit.org/changeset/42333
мы использовали следующий подход в одном из наших веб-сайтов от 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>
придумал это, и это, кажется, работает по крайней мере в Firefox и браузере Opera.
if(top != self) { top.onbeforeunload = function() {}; top.location.replace(self.location.href); }
учитывая текущий стандарт HTML5, который ввел песочницу для iframe, все коды перебора кадров, представленные на этой странице, могут быть отключены, когда злоумышленник использует песочницу, потому что он ограничивает iframe следующим:
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пожалуйста, смотрите: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox
Теперь рассмотрим злоумышленник использовал следующий код для размещения вашего сайта в iframe:
<iframe src="URI" sandbox></iframe>тогда весь код перебора фреймов JavaScript не будет выполнен.
после проверки всего кода шины кадра, только эта защита работает во всех случаях:
<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>что первоначально предложенная Gustav Rydstedt, Elie Bursztein, Dan Boneh, and Collin Jackson (2010)
после обдумывания этого на некоторое время, я считаю, что это покажет им, кто босс...
if(top != self) { window.open(location.href, '_top'); }используя
_topв качестве целевого параметраwindow.open()запустит его в том же окне.
if (top != self) { top.location.replace(location); location.replace("about:blank"); // want me framed? no way! }
Итак, мы знаем, что были в кадре. Поэтому нам расположение.href на другую специальную страницу с путем в качестве переменной GET. Теперь мы объясним пользователю, что происходит, и предоставим ссылку с опцией target="_TOP". Это просто и, вероятно, будет работать (не тестировал его), но это требует некоторого взаимодействия с пользователем. Может быть, вы могли бы указать оскорбляющий сайт пользователю и сделать зал стыда щелкающих джекеров на ваш сайт где-нибудь.. Просто идея, но это ночная работа..
все предложенные решения непосредственно заставляют изменить расположение верхнего окна. Что делать, если пользователь хочет, чтобы кадр был там? Например верхний кадр на изображении результатов поисковых систем.
Я написал прототип, где по умолчанию все входы (ссылки, формы и элементы ввода) отключены и/или ничего не делают при активации.
Если обнаружен содержащий кадр, входы остаются отключенными, и в верхней части страницы отображается предупреждающее сообщение. Этот предупреждающее сообщение содержит ссылку, которая откроет безопасную версию страницы в новом окне. Это предотвращает использование страницы для clickjacking, в то же время позволяя пользователю просматривать содержимое в других ситуациях.
если кадр не обнаружен, входы включены.
вот код. Вам нужно установить стандартные атрибуты HTML в безопасные значения и добавить дополнительные атрибуты, содержащие фактические значения. Это, вероятно, является неполным и для полной безопасности дополнительные атрибуты (я думаю о обработчиках событий), вероятно, придется рассматривать таким же образом:
<!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>
Я собираюсь быть храбрым и бросить свою шляпу в кольцо на этом (древнем, как это), посмотрите, сколько downvotes я могу собрать.
вот моя попытка, которая, похоже, работает везде, где я ее тестировал (Chrome20, IE8 и 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); }());Я поместил этот код в
<head>и назвал его в конце<body>чтобы убедиться, что моя страница отображается, прежде чем он начинает спорить с вредоносным кодом, не знаю, если это лучший подход, МММ.как это работает?
...Я слышу, как вы спрашиваете - ну честный ответ, я не действительно знаю. Это заняло много времени, чтобы заставить его работать везде, где я тестировал, и точный эффект, который он имеет, немного варьируется в зависимости от того, где вы его запускаете.
вот за это:
- установите функцию для запуска с минимально возможным интервалом. Основная концепция, лежащая в основе любого реалистичного решения, которые я видел, - это заполнить планировщик большим количеством событий, чем кадр buster-buster.
- каждый раз, когда функция срабатывает, попробуйте изменить расположение верхней рамы. Довольно очевидное требование.
- также запланируйте функцию для немедленного запуска, которая займет много времени для завершения (тем самым блокируя кадр buster-buster от вмешательства в изменение местоположения). Я выбрал синхронный XMLHttpRequest, потому что это единственный механизм, который я могу придумать это не требует (или, по крайней мере, не требует) взаимодействия с пользователем и не пережевывает процессорное время пользователя.
для меня
http://mysite.tld/page-that-takes-a-while-to-load(цель XHR) я использовал PHP-скрипт, который выглядит так:<?php sleep(5);что происходит?
- Chrome и Firefox подождите 5 секунд, пока XHR завершится, а затем успешно перенаправьте на URL-адрес обрамленной страницы.
- IE перенаправляет довольно много немедленно
не можете ли Вы избежать времени ожидания в Chrome и Firefox?
видимо, нет. Сначала я указал XHR на URL, который вернет 404 - это не сработало в Firefox. Затем я попробовал
sleep(5);подход, который я в конечном итоге приземлился на этот ответ, затем я начал играть с длиной сна по-разному. Я не мог найти никакой реальной модели поведения, но я обнаружил, что если она слишком коротка, в частности Firefox будет не играйте в мяч (Chrome и IE, похоже, довольно хорошо себя ведут). Я не знаю, что определение "слишком короткий" в реальном выражении, но 5 секунд кажется работать каждый раз.
если какие-либо проходящие JavaScript ниндзя хотят объяснить немного лучше, что происходит, почему это (вероятно) неправильно, ненадежно, худший код, который они когда-либо видели и т. д. Я с удовольствием послушаю.
по состоянию на 2015 год, вы должны использовать CSP2 в
frame-ancestors:X-Frame-Options: DENYЯ бы посоветовал включить оба в любом случае, в противном случае ваш сайт будет продолжать быть уязвимым для Clickjacking выпады в старых браузерах, и конечно вы получил бы нежелательное обрамление даже без злого умысла. Большинство браузеров обновляют автоматически в эти дни, однако вы все еще склонны получать корпоративных пользователей, застрявших на старых версиях Internet Explorer по причинам совместимости устаревших приложений.
Ну, вы можете изменить значение счетчика, но это, очевидно, хрупкое решение. Вы можете загрузить свой контент через AJAX после того, как вы определили, что сайт не находится в кадре - также не отличное решение, но он, надеюсь, избегает запуска события beforeunload (я предполагаю).
Edit: еще одна идея. Если вы обнаружите, что находитесь во фрейме, попросите пользователя отключить javascript, прежде чем щелкнуть ссылку, которая приведет вас к нужному URL (передача строки запроса, которая позволяет страница знает, чтобы сказать пользователю, что они могут повторно включить javascript, как только они там).
Edit 2: Go nuclear - если вы обнаружите, что находитесь в кадре, просто удалите содержимое тела документа и распечатайте какое-то неприятное сообщение.
Edit 3: Можете ли вы перечислить верхний документ и установить все функции в null (даже анонимные)?
Если вы добавите предупреждение сразу после кода buster, то предупреждение остановит поток javascript, и это позволит загрузить страницу. Это то, что делает StackOverflow, и он вылетает из моих iframes, даже когда я использую фрейм busting buster. Он также работал с моей простой тестовой страницы. Это было проверено только в 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>
Я думаю, что вы были почти там. Вы пробовали:
window.parent.onbeforeunload = null; window.parent.location.replace(self.location.href);или же:
window.parent.prevent_bust = 0;Примечание: я на самом деле не проверить это.
а как насчет повторного вызова Бастера? Это создаст условия гонки, но можно надеяться, что Бастер выйдет на первое место:
(function() { if(top !== self) { top.location.href = self.location.href; setTimeout(arguments.callee, 0); } })();
Если вы посмотрите на значения, возвращаемые
setInterval()обычно это одинарные цифры, поэтому вы можете отключить все такие прерывания с помощью одной строки кода:for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
возможно, я только что получил способ сломать фрейм buster buster javascript. Используя getElementsByName в моей функции javascript, я установил цикл между frame buster и фактическим сценарием frame buster buster. проверьте этот пост. http://www.phcityonweb.com/frame-buster-buster-buster-2426
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, и так как setTimeout возвращает "последний интервал или тайм-аут, созданный + 1", и так как top.clearInterval все еще доступен, это победит черные шляпы атакуют фреймовые веб-сайты, которые описаны выше.
используйте htaccess, чтобы избежать высокого домкрата набора фреймов, iframe и любого контента, такого как изображения.
RewriteEngine on RewriteCond %{HTTP_REFERER} !^http://www\.yoursite\.com/ [NC] RewriteCond %{HTTP_REFERER} !^$ RewriteRule ^(.*)$ /copyrights.html [L]это покажет страницу авторских прав вместо ожидаемого.
Comments