🛡️ CSPビルダー
Content-Security-Policy(CSP)は、ブラウザに「どこから読み込んだリソースなら実行してよいか」を伝えるヘッダーです。XSSが発生しても攻撃コードの実行を止められる、最後の砦にあたります。主要なディレクティブごとに許可するソースを選ぶだけで、そのまま貼り付けられるCSPを組み立てます。
プリセットから始める
default-src 'none' からはじめ、必要なものだけ自サイトに限定して開けます。新規サイトはここから調整するのが理想です。
React / Vue などのSPA向け。CSS-in-JSのために style-src だけ 'unsafe-inline' を許し、画像とWorkerに blob: を開けています。
既存サイトにいきなり厳しいCSPを入れると壊れます。まずこの内容を Report-Only で流し、違反レポートを見ながら締めていく用途向けです。そのまま本番の強制ポリシーにしないでください。
ディレクティブの設定
ディレクティブ名をクリックすると、その項目のオン・オフを切り替えられます。ソースが1つも選ばれていないディレクティブは出力に含まれません。
他のディレクティブが未指定のときの既定値。まずここを絞り込むのが基本です。
JavaScriptの読み込み元。XSS対策として最も重要な項目です。
CSSの読み込み元。CSS-in-JSを使う場合は 'unsafe-inline' が必要になることがあります。
画像の読み込み元。Base64画像を使うなら data: が必要です。
fetch / XHR / WebSocket / EventSource の接続先。
Webフォントの読み込み元。
iframeとして埋め込むことを許可する読み込み元。
自サイトをiframeに埋め込める側の指定。クリックジャッキング対策になります。
<base>タグで指定できるURL。'self' に固定すると相対URLの乗っ取りを防げます。
フォームの送信先。外部への送信を防ぎます。
<object> / <embed> の読み込み元。'none' の指定を強く推奨します。
<audio> / <video> の読み込み元。
Worker / SharedWorker / ServiceWorker の読み込み元。
生成されたポリシー
オンにすると Content-Security-Policy-Report-Only として出力します。ブラウザは違反を検出しても実際にはブロックせず、コンソールとレポート送信先に記録するだけになります。既存サイトに導入するときは、まずこちらで様子を見てください。
13件のディレクティブを出力しています。
default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; font-src 'self' data:; frame-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'; media-src 'self'; worker-src 'self' blob:
Webサーバーやアプリケーション側でこのヘッダーを付与します。meta タグより優先度が高く、frame-ancestors も有効なため、可能な限りこちらを使ってください。
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; font-src 'self' data:; frame-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'; media-src 'self'; worker-src 'self' blob:
HTMLの<head>内、できるだけ先頭に置いてください。metaタグでは frame-ancestors / report-uri / sandbox が無効なため、出力から frame-ancestors を除いています。クリックジャッキング対策が必要な場合はHTTPヘッダー形式を使ってください。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; font-src 'self' data:; frame-src 'self'; base-uri 'self'; form-action 'self'; object-src 'none'; media-src 'self'; worker-src 'self' blob:">
設定の診断
スクリプトほどではありませんが、CSSインジェクションによる情報の抜き取りや画面偽装の余地が残ります。CSS-in-JSの都合でどうしても必要な場合を除き、外部CSSファイルに寄せてください。
nonce と hash の使い方
インラインスクリプトをどうしても残したい場合、'unsafe-inline' の代わりに nonce か hash を使います。どちらも「このスクリプトだけは許可する」とピンポイントで指定する仕組みなので、攻撃者が注入したスクリプトは実行されません。
リクエストごとにサーバー側でランダムな値(16バイト以上、Base64推奨)を生成し、ヘッダーとタグの両方に同じ値を書きます。
Content-Security-Policy: script-src 'self' 'nonce-r4nd0mV4lu3' <script nonce="r4nd0mV4lu3"> // このスクリプトだけ実行が許可される </script>
値を毎回変えることが必須です。固定値やページキャッシュへの埋め込みは、攻撃者に値を知られるため意味がなくなります。静的ホスティングのようにリクエストごとの生成ができない環境では、nonce は使えません。
スクリプトの中身そのもののハッシュ値を許可リストに書きます。中身が固定のインラインスクリプト向けで、静的サイトでも使えます。
Content-Security-Policy: script-src 'self' 'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8='
<script>alert('Hello, world.');</script>対象は<script>タグの中身そのもの(前後の改行や空白も含む)です。sha256 / sha384 / sha512 が使えます。ハッシュ値は、違反時にブラウザのコンソールに表示される値をそのまま貼るのが確実です。スクリプトを1文字でも変えると値が変わるので、ビルド時に自動生成する運用にしてください。
nonce または hash が指定されている場合、対応ブラウザは 'unsafe-inline' を無視します。そのため、古いブラウザ向けの保険として 'unsafe-inline' を残す書き方は成立します。逆に、'strict-dynamic' を併記すると、nonce付きスクリプトが動的に読み込んだスクリプトも許可され、ホスト名の許可リストは無視されます。
関連ツール
URLを入力すると、実際に配信されているCSPやHSTS、X-Frame-Options などの設定を採点します。作ったCSPが正しく反映されたかの確認にどうぞ。
※ 入力内容はすべてブラウザ内(お使いの端末のJavaScript)で処理しており、サーバーへ送信・保存することは一切ありません。
※ 生成したポリシーは、必ずステージング環境や Report-Only で動作確認してから本番へ適用してください。CSPは設定を誤るとサイトの機能が動かなくなります。
※ 本ツールは主要なディレクティブのみを扱います。report-to / upgrade-insecure-requests / sandbox などが必要な場合は、生成結果に手で追記してください。