Webアプリケーションのセキュリティ対策というと、SQLインジェクションやXSS対策のコードレベルの実装を思い浮かべる方が多いかもしれません。しかし、HTTPレスポンスヘッダーを適切に設定するだけで防げる攻撃は数多く存在します。
筆者の経験では、セキュリティ診断で指摘される項目の約3割がHTTPヘッダーの設定不備に起因するものです。設定自体は比較的簡単であるにもかかわらず、見落とされがちな領域と言えます。本記事では、特に重要な3つのセキュリティヘッダーについて、設定方法と実践的な注意点を解説します。
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
各ディレクティブの意味は以下の通りです。
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に切り替える流れが安全です。
インラインスクリプトを許可する必要がある場合、'unsafe-inline' ではなくnonceを使用するのがベストプラクティスです。
# ヘッダー設定
Content-Security-Policy: script-src 'nonce-abc123def456'
# HTML側
<script nonce="abc123def456">
// この中のスクリプトのみ実行が許可される
console.log('Allowed script');
</script>
nonceはリクエストごとにランダムに生成する必要があります。サーバーサイドのテンプレートエンジンで動的に埋め込む仕組みが一般的です。
HSTSは、ブラウザに対して「このドメインには必ずHTTPSで接続すること」を指示するヘッダーです。HTTPからHTTPSへのリダイレクト中に発生する中間者攻撃(MITM)を防止できます。
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
<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は、ページが <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つに加えて、以下のヘッダーも設定しておくことを推奨します。
設定後は必ず検証を行いましょう。curlコマンドでヘッダーを確認できます。
curl -I https://your-site.example.com
また、Mozillaが提供する Observatory(observatory.mozilla.org)やSecurityHeaders.com といったオンラインツールで、設定の網羅性をスコアリングしてもらうことも有効です。
セキュリティヘッダーの設定は、比較的低コストで実施できるセキュリティ対策です。特にCSP、HSTS、X-Frame-Optionsの3つは必須と言えるレベルの重要度を持っています。段階的に導入し、Report-Onlyモードで影響を確認しながら進めることで、安全にセキュリティレベルを向上させることができます。設定したら終わりではなく、定期的な見直しも忘れずに行いましょう。