一般社団法人 全国個人事業主支援協会

COLUMN コラム

  • セキュリティヘッダーの完全ガイド:CSP・HSTS・X-Frame-Options

HTTPセキュリティヘッダーの重要性

Webアプリケーションのセキュリティ対策というと、SQLインジェクションやXSS対策のコードレベルの実装を思い浮かべる方が多いかもしれません。しかし、HTTPレスポンスヘッダーを適切に設定するだけで防げる攻撃は数多く存在します。

筆者の経験では、セキュリティ診断で指摘される項目の約3割がHTTPヘッダーの設定不備に起因するものです。設定自体は比較的簡単であるにもかかわらず、見落とされがちな領域と言えます。本記事では、特に重要な3つのセキュリティヘッダーについて、設定方法と実践的な注意点を解説します。

Content-Security-Policy(CSP)

CSPは、ブラウザが読み込むリソースの提供元を制御するための仕組みです。XSS攻撃の緩和に極めて効果的であり、現代のWebセキュリティにおいて最も重要なヘッダーの一つです。

基本的な設定

CSPはディレクティブの組み合わせで構成されます。まずは基本的な設定例を見てみましょう。

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.googleapis.com; connect-src 'self' https://api.example.com

各ディレクティブの意味は以下の通りです。

  • default-src:他のディレクティブで指定されていないリソースのデフォルトポリシー
  • script-src:JavaScriptの読み込み元を制限
  • style-src:CSSの読み込み元を制限
  • img-src:画像の読み込み元を制限
  • connect-src:XMLHttpRequestやFetch APIの接続先を制限

Nginxでの設定例

server {
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;" always;
}

段階的な導入アプローチ

CSPをいきなり厳格に設定すると、既存の機能が動作しなくなる可能性があります。そこで推奨されるのが、Content-Security-Policy-Report-Only ヘッダーを使った段階的な導入です。

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

このヘッダーを設定すると、ポリシー違反があってもブロックせず、指定したエンドポイントに違反レポートを送信します。本番環境でしばらく運用して違反内容を分析し、ポリシーを調整してから実際のCSPに切り替える流れが安全です。

nonceベースの設定

インラインスクリプトを許可する必要がある場合、'unsafe-inline' ではなくnonceを使用するのがベストプラクティスです。

# ヘッダー設定
Content-Security-Policy: script-src 'nonce-abc123def456'

# HTML側
<script nonce="abc123def456">
// この中のスクリプトのみ実行が許可される
console.log('Allowed script');
</script>

nonceはリクエストごとにランダムに生成する必要があります。サーバーサイドのテンプレートエンジンで動的に埋め込む仕組みが一般的です。

HTTP Strict Transport Security(HSTS)

HSTSは、ブラウザに対して「このドメインには必ずHTTPSで接続すること」を指示するヘッダーです。HTTPからHTTPSへのリダイレクト中に発生する中間者攻撃(MITM)を防止できます。

設定例

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

  • max-age:HSTS ポリシーの有効期間(秒)。31536000は1年間
  • includeSubDomains:サブドメインにもポリシーを適用
  • preload:ブラウザのプリロードリストへの登録を示す

Apacheでの設定例

<VirtualHost *:443>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</VirtualHost>

導入時の注意点

HSTSは一度設定するとブラウザにキャッシュされるため、HTTPS環境に問題がある状態で設定するとサイトにアクセスできなくなります。まずは max-age=300(5分)など短い値で動作を確認し、問題がなければ段階的に延長するのが安全です。また、includeSubDomains を設定する場合は、すべてのサブドメインがHTTPSに対応していることを事前に確認してください。

X-Frame-Options

X-Frame-Optionsは、ページが <iframe><frame> 内に埋め込まれることを制御するヘッダーです。クリックジャッキング攻撃の防止に有効です。

設定オプション

# 完全にフレーム内表示を禁止
X-Frame-Options: DENY

# 同一オリジンからのフレーム内表示のみ許可
X-Frame-Options: SAMEORIGIN

なお、CSPの frame-ancestors ディレクティブはX-Frame-Optionsの上位互換であり、より柔軟な制御が可能です。

Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com

ただし、古いブラウザとの互換性を考慮して、X-Frame-OptionsとCSPの frame-ancestors を併用するのが推奨されます。

その他の重要なセキュリティヘッダー

上記3つに加えて、以下のヘッダーも設定しておくことを推奨します。

  • X-Content-Type-Options: nosniff:ブラウザによるMIMEタイプの推測を防止
  • Referrer-Policy: strict-origin-when-cross-origin:リファラー情報の送信範囲を制御
  • Permissions-Policy:カメラ、マイク、位置情報などのブラウザ機能へのアクセスを制御

設定の検証方法

設定後は必ず検証を行いましょう。curlコマンドでヘッダーを確認できます。

curl -I https://your-site.example.com

また、Mozillaが提供する Observatory(observatory.mozilla.org)やSecurityHeaders.com といったオンラインツールで、設定の網羅性をスコアリングしてもらうことも有効です。

まとめ

セキュリティヘッダーの設定は、比較的低コストで実施できるセキュリティ対策です。特にCSP、HSTS、X-Frame-Optionsの3つは必須と言えるレベルの重要度を持っています。段階的に導入し、Report-Onlyモードで影響を確認しながら進めることで、安全にセキュリティレベルを向上させることができます。設定したら終わりではなく、定期的な見直しも忘れずに行いましょう。

この記事をシェアする

  • Twitterでシェア
  • Facebookでシェア
  • LINEでシェア