[英]Frame Buster Buster ... buster code needed
假设您不希望其他网站在<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()
设置一个每毫秒触发一次的计时器,如果它看到计数器增加,则将当前位置更改为攻击者控制的服务器我的问题是——这更像是一个 JavaScript 难题而不是一个实际问题——你怎么能打败破坏框架的破坏者?
我有一些想法,但在我的测试中没有任何效果:
onbeforeunload = null
清除onbeforeunload
事件onbeforeunload = null
alert()
停止进程让用户知道它正在发生,但不会以任何方式干扰代码; 单击“确定”让破坏继续正常进行setInterval()
计时器我不是一个 JavaScript 程序员,所以这是我对你的挑战:嘿,破坏者,你能破坏框架破坏者吗?
FWIW,大多数当前浏览器都支持X-Frame-Options: deny指令,即使禁用脚本也能工作。
IE8:
http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspx
火狐 (3.6.9)
https://bugzilla.mozilla.org/show_bug.cgi?id=475530
https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header
铬/网络套件
http://blog.chromium.org/2010/01/security-in-depth-new-security-features.html
http://trac.webkit.org/changeset/42333
我不确定这是否可行 - 但如果你不能打破框架,为什么不只是显示一个警告。 例如,如果您的页面不是“首页”,则创建一个尝试打破框架的 setInterval 方法。 如果尝试 3 或 4 次后,您的页面仍然不是首页 - 创建一个 div 元素来覆盖整个页面(模式框),并带有一条消息和一个链接,例如...
您正在未经授权的框架窗口中查看此页面 - (等等……潜在的安全问题)
单击此链接以解决此问题
不是最好的,但我看不出他们有什么办法可以摆脱这种情况。
我们在来自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);
}
考虑到当前为 iframe 引入沙箱的 HTML5 标准,当攻击者使用沙箱时,可以禁用此页面中提供的所有框架破坏代码,因为它限制了 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 和 Collin Jackson 提出(2010 年)
想了一会儿,相信这会告诉他们谁是老大……
if(top != self) {
window.open(location.href, '_top');
}
使用_top
作为window.open()
的目标参数将在同一窗口中启动它。
截至 2015 年,您应该为此使用 CSP2 的frame-ancestors
指令。 这是通过 HTTP 响应标头实现的。
例如
Content-Security-Policy: frame-ancestors 'none'
当然,目前支持 CSP2 的浏览器并不多,因此包含旧的X-Frame-Options
标头是明智之举:
X-Frame-Options: DENY
无论如何,我建议两者都包含在内,否则您的网站将继续容易受到旧浏览器中的点击劫持攻击,当然,即使没有恶意,您也会获得不受欢迎的框架。 如今,大多数浏览器都会自动更新,但是由于旧版应用程序兼容性的原因,您仍然倾向于让企业用户停留在旧版本的 Internet Explorer 上。
所有建议的解决方案都直接强制改变顶部窗口的位置。 如果用户想要框架在那里怎么办? 例如搜索引擎图像结果中的顶部框架。
我写了一个原型,默认情况下所有输入(链接、表单和输入元素)都被禁用和/或在激活时什么都不做。
如果检测到包含框架,输入将保持禁用状态,并在页面顶部显示警告消息。 警告消息包含一个链接,该链接将在新窗口中打开该页面的安全版本。 这可以防止页面被用于点击劫持,同时仍然允许用户在其他情况下查看内容。
如果未检测到包含帧,则启用输入。
这是代码。 您需要将标准 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>
if (top != self) {
top.location.replace(location);
location.replace("about:blank"); // want me framed? no way!
}
我会勇敢地把我的帽子扔进这个(虽然古老)的戒指上,看看我能收集多少反对票。
这是我的尝试,它似乎在我测试过的任何地方都有效(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>
的末尾调用它以确保我的页面在开始与恶意代码争论之前呈现,不知道这是否是最好的方法,YMMV。
它是如何工作的?
......我听到你问-好诚实的回答是,我真的不知道。 我花了很多心思才让它在我测试的任何地方都能工作,而且它的确切效果会因您运行它的位置而略有不同。
这是它背后的想法:
对于我的http://mysite.tld/page-that-takes-a-while-to-load
(XHR 的目标),我使用了一个如下所示的 PHP 脚本:
<?php sleep(5);
发生什么了?
您不能避免 Chrome 和 Firefox 中的等待时间吗?
显然不是。 起初,我将 XHR 指向一个会返回 404 的 URL - 这在 Firefox 中不起作用。 然后我尝试了sleep(5);
我最终采用了这个答案的方法,然后我开始以各种方式玩弄睡眠长度。 我找不到这种行为的真正模式,但我确实发现如果它太短,特别是 Firefox 将无法正常运行(Chrome 和 IE 似乎表现得相当好)。 我不知道“太短”的实际定义是什么,但 5 秒似乎每次都有效。
如果任何通过 Javascript 的忍者想要更好地解释正在发生的事情,为什么这(可能)是错误的、不可靠的、他们见过的最糟糕的代码等等,我会很乐意倾听。
好的,所以我们知道这是在一个框架中。 所以我们将location.href 指向另一个特殊页面,将路径作为GET 变量。 我们现在向用户解释发生了什么,并提供一个带有 target="_TOP" 选项的链接。 它很简单,可能会工作(尚未测试过),但它需要一些用户交互。 也许您可以向用户指出有问题的网站,并在您的网站某处让点击劫持者感到羞耻......只是一个想法,但它夜间工作..
如果您在 buster 代码之后立即添加警报,则警报将停止 javascript 线程,并让页面加载。 这就是 StackOverflow 所做的,即使我使用 frame busting buster,它也会从我的 iframe 中删除。 它也适用于我的简单测试页面。 这仅在 Windows 上的 Firefox 3.5 和 IE7 中进行过测试。
代码:
<script type="text/javascript">
if (top != self){
top.location.replace(self.location.href);
alert("for security reasons bla bla bla");
}
</script>
好吧,您可以修改计数器的值,但这显然是一个脆弱的解决方案。 在确定站点不在框架内之后,您可以通过 AJAX 加载您的内容 - 这也不是一个很好的解决方案,但它希望避免触发 on beforeunload 事件(我假设)。
编辑:另一个想法。 如果您检测到您在框架中,请在单击将您带到所需 URL 的链接之前要求用户禁用 javascript(传递一个查询字符串,让您的页面知道告诉用户他们可以在他们重新启用 javascript 后重新启用在那里)。
编辑 2:去核 - 如果你检测到你在一个框架中,只需删除你的文档正文内容并打印一些令人讨厌的消息。
编辑 3:您能否枚举顶级文档并将所有函数设置为 null(甚至是匿名函数)?
如果您查看setInterval()
返回的值,它们通常是个位数,因此您通常可以使用一行代码禁用所有此类中断:
for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
我想你快到了。 你有没有尝试过:
window.parent.onbeforeunload = null;
window.parent.location.replace(self.location.href);
或者,或者:
window.parent.prevent_bust = 0;
注意:我实际上并没有对此进行测试。
我可能刚刚找到了一种方法来破坏 frame buster buster javascript。 在我的 javascript 函数中使用 getElementsByName,我在 frame buster 和实际 frame buster buster 脚本之间设置了一个循环。 看看这个帖子。 http://www.phcityonweb.com/frame-buster-buster-buster-2426
反复呼叫破坏者又如何? 这会造成竞争条件,但人们可能希望破坏者名列前茅:
(function() {
if(top !== self) {
top.location.href = self.location.href;
setTimeout(arguments.callee, 0);
}
})();
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]
这将显示版权页面而不是预期的页面。
您可以通过使用postMessage()
方法来改进整个想法,以允许某些域访问和显示您的内容,同时阻止所有其他域。 首先,父容器必须通过向试图显示您的页面的iframe
的contentWindow
发布消息来介绍自己。 您的页面必须准备好接受消息,
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// Use event.origin here like
if(event.origin == "https://perhapsyoucantrustthisdomain.com"){
// code here to block/unblock access ... a method like the one in user1646111's post can be good.
}
else{
// code here to block/unblock access ... a method like the one in user1646111's post can be good.
}
}
最后不要忘记在等待load
事件的函数中包装一些东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.