Content Security Policy Lv2 (CSP2)で ページを他所からフレーム利用させない

ストップ
©いらすとや.

Content Security Policyは基本的にはそれ(CSP)を設定するページで使用する要素を許可するものです。ページでスクリプトを使用するならそのスクリプトやスクリプトの置いてあるホストをscript-srcディレクティブで許可、ページでCSSを使用するならそのCSSやCSSを置いてあるホストをstyle-srcディレクティブで、フレームを使用するならそのフレームの置いてあるホストなどをframe-srcディレクティブで、という風に指定して許可する。

しかし、気色の違うものがあって、フレーム用のframe-ancestorsというディレクティブがそれ。このframe-ancestorsは、それをCSPで指定しているページを他所から使用されることを許可するもの。自身のサイトのページでframe-ancestorsで許可しなければ見ず知らずの他所サイトのiframe内であなたのページを表示されなくなります。ただし、frame-ancestorディレクティブが無い場合は他所の全てのサイトからiframeで読み込まれることを許可しているのと同じになります。他所のウェブサイトからあなたのページをiframeで読み込まれたくなければframe-ancestorディレクティブを指定しましょう。
まぁ、iframeを不許可にしたところでウェブスクレイピングで勝手に使われることはあるかもだけど、この記事とは関係ないのでそれは無視。
今回はそのframe-ancestorsディレクティブを実際に使ってみて動作を確認します。

frame-ancestorsで他所のサイトからiframeで読み込むことを許可する場合

https://denwa.intaa.net/iframe_sample1.phpというページでframe-ancestorsを設定し、他所のサイト「がとらぼ」(intaa.net)を許可する。
Content-Security-Policy: frame-ancestors intaa.net;
そのページを「がとらぼ」(他所のサイト側)でiframe内に読み込む。(↓)は画像ではなく実際にiframeで読み込んでいます。

「がとらぼ」側のiframeタグ:
<iframe src="https://denwa.intaa.net/iframe_sample1.php" width="800" height="480" title="denwa.intaa.net IFRAMEサンプル 1"></iframe>
「がとらぼ」のホストが許可されているので外人の電話オペレータさんたちが写った写真を含むページが表示されている筈。

frame-ancestorsで他所のサイトからiframeで読み込むことを許可しない場合

https://denwa.intaa.net/iframe_sample2.phpというページでframe-ancestorsを設定し、どこからもiframeでの表示を許可しない ' none' を指定する。
Content-Security-Policy: frame-ancestors 'none';
そのページを「がとらぼ」(他所のサイト側)でiframe内に読み込む。(↓)は画像ではなく実際にiframeで読み込みますが許可されていないのでページは表示されていない筈です。

「がとらぼ」側のiframeタグ:
<iframe src="https://denwa.intaa.net/iframe_sample2.php" width="800" height="480" title="denwa.intaa.net IFRAMEサンプル 2"></iframe>
全てのページからiframeで読み込まれることを許可していないので「がとらぼ」のiframeでは接続が拒否されて表示されない。

frame-ancestorsを使って積極的に不許可にしましょう

CSPはウェブサイト側で指定しますが、それをブラウザが解釈して動作し閲覧者を守るセキュリティです。ブラウザが対応していなければ指定した動作にはなりません。frame-ancestorsはIE以外のメジャーブラウザの最近のバージョンは対応します。ブラウザがframe-ancestorsに対応しない場合の動作はframe-ancestors未指定と同じで全て許可です。
殆どのウェブサイトは他所からiframeで読み込まれることを許可する必要がない筈。むしろ悪用を避けるために積極的に禁止すべき。つまりほぼ無条件で frame-ancestors 'none';frame-ancestors 'self'; (自身のホストは許可)を指定するのが良いと思われます。

おまけ: (X-Frame-Optionsヘッダ)
frame-ancestors 'none'は、Content-Security-PolicyヘッダではなくX-Frame-Options: DENY;
frame-ancestors 'self'は、Content-Security-PolicyヘッダではなくX-Frame-Options: SAMEORIGIN;
のようにX-Frame-Optionsヘッダで指定することも可能です。

ホストを許可する場合はX-Frame-Options: ALLOW-FROM host.example.com のように指定することができましたが、これは過去の話です。最近のメジャーブラウザではALLOW-FROMは廃止されているのでCSPのframe-ancestorsを使いましょう。
なお、X-Frame-OptionsはHTMLヘッダではなくHTTPヘッダで指定してください。