Web セキュリティ

CSP (コンテンツセキュリティポリシー)

約 4 分で読めます

CSP (Content Security Policy) とは

CSP (Content Security Policy) とは、Web ページが読み込めるリソース (スクリプト、スタイルシート、画像、フォントなど) の提供元をサーバー側で制御する HTTP レスポンスヘッダーです。ブラウザは CSP で許可されていないリソースの読み込みや実行をブロックするため、XSS (クロスサイトスクリプティング) 攻撃の被害を大幅に軽減できます。

XSS の根本対策は出力エスケープですが、実装の漏れは完全には排除できません。CSP は「たとえ XSS 脆弱性が存在しても、攻撃者のスクリプトを実行させない」という多層防御の役割を果たします。セキュリティヘッダーの中でも最も強力かつ複雑なヘッダーの 1 つです。

主要なディレクティブ

CSP は複数のディレクティブで構成され、リソースの種類ごとに許可する提供元を指定します。

  • default-src: 他のディレクティブで明示的に指定されていないリソースのデフォルトポリシー。default-src 'self' は同一オリジンからのリソースのみを許可する
  • script-src: JavaScript の読み込み元を制御する。XSS 対策の核心となるディレクティブ。'unsafe-inline' を避け、nonce または hash を使用することが推奨される
  • style-src: CSS の読み込み元を制御する
  • img-src: 画像の読み込み元を制御する
  • connect-src: fetch、XMLHttpRequest、WebSocket の接続先を制御する
  • font-src: Web フォントの読み込み元を制御する
  • frame-src: iframe の埋め込み元を制御する。クリックジャッキング対策にも関連する
  • frame-ancestors: 自サイトを iframe に埋め込める親ページのオリジンを制御する。X-Frame-Options の後継

ソース値の指定方法

  • 'self': 同一オリジン
  • 'none': すべてブロック
  • 'nonce-{random}': 特定の nonce 値を持つインラインスクリプト/スタイルのみ許可
  • 'strict-dynamic': nonce で許可されたスクリプトが動的に読み込むスクリプトも許可する
  • 具体的なドメイン: https://cdn.example.com

段階的な導入手順

CSP の導入は、既存のサイトを壊さないよう段階的に進めることが重要です。

ステップ 1: Report-Only モードで監視

Content-Security-Policy-Report-Only ヘッダーを使用すると、ポリシー違反を検知してレポートするだけで、リソースのブロックは行いません。まずこのモードで現在のサイトがどのようなリソースを読み込んでいるかを把握します。

ステップ 2: 基本ポリシーの策定

レポートの分析結果に基づき、必要なリソースの提供元をホワイトリストに追加します。最初は緩めのポリシーから始め、段階的に厳格化していきます。

ステップ 3: 本番適用と継続的な監視

Content-Security-Policy ヘッダーに切り替えて本番適用します。report-uri または report-to ディレクティブでポリシー違反のレポートを継続的に収集し、誤検知や新たなリソース要件に対応します。

推奨される厳格なポリシーの例

default-src 'none'; script-src 'self' 'nonce-{random}' 'strict-dynamic'; style-src 'self' 'nonce-{random}'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'

このポリシーは、インラインスクリプトを nonce で制御し、'strict-dynamic' で動的に読み込まれるスクリプトも許可します。

CSP と他のセキュリティヘッダーの連携

CSP は単独でも強力ですが、他のセキュリティヘッダーと組み合わせることで、より堅牢な防御を構築できます。

  • HSTS との併用: HTTPS を強制し、中間者攻撃による CSP ヘッダーの改ざんを防ぐ。CSP の効果を最大限に発揮するには HTTPS が前提
  • X-Content-Type-Options: nosniff: MIME タイプスニッフィングを防止し、スクリプトとして解釈されるべきでないリソースの実行を阻止する
  • CORS との関係: CSP はリソースの読み込み元を制御し、CORS はクロスオリジンリクエストのアクセス権を制御する。両者は補完的な関係にある

CSP の導入は初期コストがかかりますが、XSSクリックジャッキングに対する防御力を飛躍的に高めます。新規プロジェクトでは開発初期から CSP を設計に組み込むことで、後からの導入に比べて大幅にコストを削減できます。

よくある誤解

CSP を設定すれば XSS 対策は不要
CSP は XSS の被害を軽減する多層防御の一層であり、XSS の根本対策 (出力エスケープ) を代替するものではない。CSP のバイパス手法も研究されており、出力エスケープ + CSP の両方を実装することが推奨される。
CSP は設定が難しいので小規模サイトには不要
小規模サイトでも XSS のリスクは存在する。最小限のポリシー (例: default-src 'self'; script-src 'self') から始めれば導入は容易。Report-Only モードで影響を確認しながら段階的に厳格化できる。

関連用語

関連記事