假设你不希望其他网站在<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>

这段代码执行以下操作:

每次浏览器试图通过窗口导航离开当前页面时,递增一个计数器。Onbeforeunload事件处理程序 设置一个计时器,通过setInterval()每毫秒触发一次,如果它看到计数器增加,则将当前位置更改为攻击者控制的服务器 该服务器提供一个HTTP状态码为204的页面,这不会导致浏览器在任何地方导航

我的问题是——这更像是一个JavaScript难题,而不是一个实际问题——如何打败框架破坏破坏者?

我有一些想法,但在我的测试中没有什么管用:

试图通过onbeforeunload = null清除onbeforeunload事件没有效果 添加alert()会停止进程,让用户知道它正在发生,但不会以任何方式干扰代码;单击OK,让破坏照常进行 我想不出任何方法来清除setInterval()定时器

我不是一个很好的JavaScript程序员,所以这是我对你的挑战:嘿,老兄,你能打破框架破坏老兄吗?


当前回答

setInterval和setTimeout创建一个自动递增的时间间隔。每次调用setTimeout或setInterval时,这个数字都会增加1,因此如果调用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个同时工作的setinterval和setTimeouts,并且由于setTimeout返回“最后创建的间隔或超时+ 1”,并且由于top。clearInterval仍然是可访问的,这将击败黑帽攻击框架网站上面所描述的。

其他回答

那重复地叫假人老兄呢?这将创建一个竞争条件,但人们可能希望buster能够脱颖而出:

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

setInterval和setTimeout创建一个自动递增的时间间隔。每次调用setTimeout或setInterval时,这个数字都会增加1,因此如果调用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个同时工作的setinterval和setTimeouts,并且由于setTimeout返回“最后创建的间隔或超时+ 1”,并且由于top。clearInterval仍然是可访问的,这将击败黑帽攻击框架网站上面所描述的。

我想到了这个,它至少在Firefox和Opera浏览器中是有效的。

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

如果您在buster代码之后添加警报,那么警报将使javascript线程停止,并让页面加载。这就是StackOverflow所做的,它破坏了我的iframes,即使当我使用框架破坏buster。它也适用于我的简单测试页面。这个功能只在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>

考虑到当前的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和Collin Jackson提出(2010)