web-dev-qa-db-ja.com

フレームバスターバスター...バスターコードが必要です

他のサイトが自分のサイトを<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"を含んだiframeから "バスト"します。 1つ小さな問題を除いて。

結局のところ、あなたのフレームを破壊するコードは破壊される可能性がありますここに示すように

<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 = nullを介してonbeforeunloadイベントをクリアしようとしても効果がありません
  • alert()を追加することで、プロセスが停止したことをユーザーに知らせますが、コードを妨げることはありませんでした。 OKをクリックすると、破裂は通常どおり継続します
  • setInterval()タイマーをクリアする方法は考えられません

私はJavaScriptプログラマーではないので、ここにあなたの私の挑戦があります:ちょっとバスター、あなたはフレームバストバスターをバストできますか?

405
Jeff Atwood

これが実行可能かどうかはわかりませんが、フレームを分割できない場合は、警告を表示しないでください。例えば、あなたのページが「トップページ」ではない場合、フレームを壊そうとするsetIntervalメソッドを作成してください。 3、4回試してもページがトップページにならない場合は、ページ全体(モーダルボックス)をカバーするdiv要素を作成し、メッセージと次のようなリンクを追加してください。

あなたはこのページを不正なフレームウィンドウに表示しています Blah blah ...潜在的なセキュリティ問題)

---(この問題を解決するにはこのリンクをクリックしてください

最善ではないが、私は彼らがそれから彼らの方法を台本にすることができる方法を見ない。

143
Hugoware
203
EricLaw

私達はから私達のウェブサイトの1つで次のアプローチを使用した 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>
33
Dungeon Hunter

これを思いついた、そしてそれは少なくともFirefoxとOperaブラウザで動作するようです。

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

サンドボックスをiframeに導入した現在のHTML5標準を考慮すると、攻撃者がサンドボックスを使用すると、このページで提供されているすべてのフレームバスティングコードを無効にすることができます。

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-if​​rame-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)

22
user1646111

しばらくこれを熟考した後、私はこれが彼らが上司であることを彼らに示すと信じています...

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

window.open()のターゲットパラメータとして_topを使用すると、同じウィンドウで起動します。

19
Josh Stodola
if (top != self) {
  top.location.replace(location);
  location.replace("about:blank"); // want me framed? no way!
}
6
Giorgio Maone

わかりました、それで私達はそれがフレームの中にあったことを知っています。そのため、location.hrefをGET変数としてパスを持つ別の特別ページに移動します。何が起こっているのかをユーザーに説明し、target = "_ TOP"オプション付きのリンクを提供します。それは単純で、おそらく動作するでしょう(それをテストしていません)、しかしそれはいくらかのユーザ対話を必要とします。たぶんあなたはユーザーに問題のあるサイトを指摘し、どこかにあなたのサイトにクリックジャッカーの恥のホールを作ることができます..ただのアイデア、しかしそれは夜働く..

5
Mike

私は勇敢になり、これに古くから私の帽子を指輪に投げ入れるつもりです。

これが私の試みです。これは私がテストしたすべての場所で動作するようです(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>の終わりからそれを呼び出して、悪意のあるコードとの議論が始まる前に自分のページが確実にレンダリングされるようにしました。

どのように動作しますか?

...私はあなたが尋ねると聞こえます - 正直な答えはそうです、私は知りません本当に知りません。私がテストしているあらゆる場所で動作するようにするには、かなり手間がかかりました。実際の効果は、実行場所によって多少異なります。

その背後にある考え方は次のとおりです。

  • 可能な限り低い間隔で実行するように関数を設定してください。私が見た現実的な解決策の背後にある基本的な概念は、フレームバスターバスターよりも多くのイベントでスケジューラを埋めることです。
  • 関数が起動するたびに、トップフレームの位置を変えてみてください。かなり明白な要件です。
  • また、機能がすぐに実行されるようにスケジュールします。これにより、完了までに時間がかかります(それによって、フレームバスターバスターが位置の変更を妨げるのを防ぎます)。同期XMLHttpRequestを選択したのは、これが私が考えることができる唯一のメカニズムであり、ユーザーの対話を必要とせず(または少なくとも要求しない)、ユーザーのCPU時間を消費しないためです。

私のhttp://mysite.tld/page-that-takes-a-while-to-load(XHRのターゲット)には、次のようなPHPスクリプトを使用しました。

<?php sleep(5);

どうなりますか?

  • ChromeとFirefoxは、XHRが完了するまで5秒間待ってから、フレーム付きページのURLに正常にリダイレクトします。
  • IEはほとんどすぐにリダイレクトします

ChromeとFirefoxの待ち時間は避けられませんか?

どうやらそうではない。最初はXHRに404を返すURLを指定しました - これはFirefoxでは機能しませんでした。それから私は結局この答えのために着手したsleep(5);アプローチを試みました、そして次に私はいろいろな方法で睡眠の長さで遊び始めました。実際の動作のパターンは見つかりませんでしたが、それが短すぎると、具体的にはFirefoxがうまく機能しないことがわかりました(ChromeおよびIEは、かなりうまく動作しているようです)。 「短すぎる」の定義が実際にはどのようなものなのかわかりませんが、5秒は毎回うまくいくようです


合格したJavascript忍者が何が起こっているのかをもう少し詳しく説明したいのであれば、なぜこれが(おそらく)間違っていて、信頼できない、彼らが今まで見た中で最悪のコードなのかなど。

5
DaveRandom

提案されたすべての解決策は、トップウィンドウの位置の変更を直接強制します。ユーザーがフレームをそこに配置したい場合はどうなりますか?たとえば、検索エンジンの画像結果の一番上のフレームです。

私は、デフォルトですべての入力(リンク、フォーム、入力要素)が無効になっている、あるいは有効になっても何もしないプロトタイプを書きました。

含まれているフレームが検出されると、入力は無効のままになり、警告メッセージがページ上部に表示されます。警告メッセージには、安全なバージョンのページを新しいウィンドウで開くためのリンクが含まれています。これにより、ユーザーが他の状況でコンテンツを表示できるようにしながら、ページがクリックジャッキングに使用されるのを防ぎます。

包含フレームが検出されない場合は、入力が有効になります。

これがコードです。標準の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>
5
Johan Stuyts

2015年現在、これにはCSP2の frame-ancestors ディレクティブを使用する必要があります。これはHTTPレスポンスヘッダを介して実装されています。

例えば.

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

もちろん、CSP2をサポートしているブラウザはそれほど多くないので、古い X-Frame-Options ヘッダーを含めるのが賢明です。

X-Frame-Options: DENY

とにかく両方を含めることをお勧めします、そうでなければあなたのサイトは古いブラウザで Clickjacking 攻撃に対して脆弱であり続けるでしょう、そしてもちろんあなたは悪意がなくても望ましくないフレーミングを得るでしょう。最近のほとんどのブラウザは自動的に更新されますが、レガシーアプリケーションの互換性の理由から、企業ユーザーが古いバージョンのInternet Explorerで動かなくなる傾向があります。

5
SilverlightFox

バスターコードの直後にアラートを追加すると、そのアラートはJavaScriptスレッドを失速させ、ページをロードさせます。これがStackOverflowの動作で、フレームバストバスターを使用している場合でも、iframeからバストします。私の簡単なテストページでもうまくいきました。これはFirefox 3.5とIE7 for windowsでのみテストされています。

コード:

<script type="text/javascript">
if (top != self){
  top.location.replace(self.location.href);
  alert("for security reasons bla bla bla");
}
</script>
4
Marius

まあ、あなたはカウンターの値を変更することができますが、それは明らかに脆弱な解決策です。サイトがフレーム内にないことを確認したら、AJAXを使用してコンテンツを読み込むことができます。これも優れた解決策ではありませんが、on beforeunloadイベントを発生させないようにします。

編集:もう一つのアイデア。フレームに入っていることを検出した場合は、目的のURLに移動するリンクをクリックする前に、JavaScriptを無効にするようユーザーに依頼してください。ある)。

編集2:核になる - 枠内にいることを検出した場合は、文書の本文の内容を削除して厄介なメッセージを印刷するだけです。

編集3:あなたは一番上のドキュメントを列挙し、(たとえ匿名のものであっても)すべての関数をnullに設定できますか?

4
RedFilter

私はあなたがほとんどそこにいたと思います。やってみました:

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

あるいは、

window.parent.prevent_bust = 0;

注:私は実際にこれをテストしませんでした。

3

setInterval()によって返される値を見ると、それらは通常1桁なので、通常は1行のコードでそのような割り込みをすべて無効にすることができます。

for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
2
Robin Nixon

同様に繰り返しバスターを呼ぶことについてはどうですか?これにより競合状態が発生しますが、バスターが上に出ることを願います。

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

私はちょうどフレームバスターバスターJavaScriptをバストする方法を得たばかりかもしれません。私のJavaScript関数でgetElementsByNameを使用して、私はフレームバスターと実際のフレームバスターバスタースクリプトの間にループを設定しました。この投稿をチェックしてください。 http://www.phcityonweb.com/frame-buster-buster-buster-2426

2
Phcityonweb

ハイジャックフレームセット、iframe、および画像などのコンテンツを回避するには、htaccessを使用します。

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

これは予想されたものの代わりに著作権ページを表示します。

0
B.F.

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個の同時setIntervalsとsetTimeoutsが動作することはほとんど前例がないので、そしてsetTimeoutは "last interval or timeout created + 1"を返すので、そしてtop.clearIntervalはまだアクセス可能なので、これはフレームへのブラックハット攻撃を打ち負かすでしょう上記のWebサイト.

0
cwallenpoole