ssecutils
Security / Browser-native guide

HTTPセキュリティヘッダー詳解

CSP、HSTS、X-Frame-Options、Permissions-Policy など、ブラウザ防御に効くヘッダーを整理します。

8Zero tracking reading surface

はじめに: 7つのヘッダで防御層を作る

Web アプリの脆弱性対策はコード側だけではありません。HTTP レスポンスヘッダでブラウザに「この挙動は禁止」「この通信ルールに従って」と指示することで、コード側の漏れを補う多層防御が成立します。

本サイト secutils 自身も securityheaders.comA評価を取得しており、本記事ではその実装例を交えながら主要ヘッダ7つを解説します。無料で、コード変更ほぼゼロで、すぐに導入できるのがセキュリティヘッダの最大の魅力です。

① Content-Security-Policy(CSP)- XSS の最後の砦

最重要のヘッダ。「このページが読み込み・実行できるリソースの出所」をブラウザに宣言します。XSS 対策の本丸が出力時エスケープなのは前提として、もしエスケープが破れた時の最後の砦がこの CSP です。

本サイトの実装例(next.config.ts から抜粋):

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'unsafe-inline' https://va.vercel-scripts.com ...;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: blob: ...;
  font-src 'self' data:;
  connect-src 'self' https://vitals.vercel-insights.com ...;
  frame-src 'self' ...;
  object-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  upgrade-insecure-requests

各ディレクティブの役割:

ディレクティブ意味
default-src 'self'未指定の他ディレクティブのフォールバック。同一オリジンのみ
script-srcJavaScript の出所制限。ここが最重要
style-srcCSSの出所制限
img-src画像の出所制限
connect-srcfetch/XHR/WebSocketの宛先制限
frame-srciframe で埋め込めるオリジン
object-src 'none'Flash等プラグインを完全禁止(推奨)
base-uri 'self'<base> タグの改ざん攻撃を防止
form-action 'self'フォーム送信先を自オリジンに限定
frame-ancestors 'none'このページの iframe 埋め込み禁止(クリックジャッキング対策)
upgrade-insecure-requestshttp:// リソースを自動で https:// に書き換え

CSP の難所: 'unsafe-inline'

本来 CSP の真価は 'unsafe-inline' を排除することにあります。<script>...</script>onclick="..." のようなインライン JS を全て禁止すると、XSS で script タグを注入されても実行できなくなる。

ただし React/Next.js のようなフレームワークは初期ハイドレーション用に必ずインライン script を出すため、'unsafe-inline' を許可しないと動きません。回避策は2つ:

  • nonce 方式: リクエストごとにランダムな nonce を発行、許可されたインライン script にだけ nonce="..." を付ける。動的レンダリングが必須になり、CDN キャッシュが効かなくなる
  • hash 方式: 許可するインライン script の SHA256 ハッシュを CSP に書く。スクリプト内容が変わるたびに更新が必要

本サイトは「Vercel 無料枠で静的化を温存」という運用要件から、'unsafe-inline' 許容の構成を選択。代わりに frame-ancestors 'none', object-src 'none', base-uri 'self' など他の防御を厚くしてA評価を取っています。

⚠ A+評価を取るには nonce/hash 方式が必須。「セキュリティ最高ランク」と「静的化による高速 + 低コスト」のトレードオフはサービスの性質で判断します。

② Strict-Transport-Security(HSTS)- HTTPS 強制

ブラウザに「このサイトは今後 HTTPS でしか接続するな」と命令するヘッダ。MITM 攻撃や HTTP→HTTPS リダイレクトの隙間を突く攻撃を防ぎます。

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
パラメータ意味
max-age=630720002年間(秒数)。ブラウザがこのサイトをHTTPS強制と覚える期間
includeSubDomainsサブドメインも HTTPS 必須にする
preloadhstspreload.org 経由でブラウザにバンドルされる宣言

重要な注意:HSTS を設定するとロールバック困難です。max-age が長期間(2年)の間、ブラウザは強制的に HTTPS を使うので、間違えて全サブドメインに includeSubDomains を効かせると、HTTP 専用の社内ツールが繋がらなくなる事故が起きえます。本番投入前に短い max-age で慣らし、徐々に伸ばすのが鉄則

③ X-Frame-Options - クリックジャッキング対策

他サイトの iframe にこのページを埋め込まれることを防ぎます。クリックジャッキング(透明な iframe を上に重ねてユーザーに気付かせず操作させる攻撃)対策。

X-Frame-Options: DENY

値の選択肢:

  • DENY: 全てのサイトから iframe 埋め込み禁止(推奨)
  • SAMEORIGIN: 同一オリジンのみ iframe 埋め込み許可
  • ALLOW-FROM uri: 特定オリジンを許可(廃止予定、CSP の frame-ancestors を使う)

X-Frame-Options と CSP の frame-ancestors は機能的に重複しており、現代では CSP 側が主流。ただし古いブラウザ互換のために両方設定するのが慣例で、本サイトも両方入れています。

④ X-Content-Type-Options - MIME スニッフィング無効化

X-Content-Type-Options: nosniff

ブラウザは時として「サーバが返した Content-Type を信用せず、内容から型を推測する」MIME スニッフィングを行います。これが脆弱性につながります:

  • サーバが画像 (image/png) として返したファイルが、内容に JS が混入していると、ブラウザが「これは JS だ」と判断して実行
  • ユーザーがアップロードした画像が実は JS で、攻撃成立

nosniff を付けると「Content-Type を信じる、推測しない」挙動になり、この攻撃面が消えます。無設定で困ることはまずないので、必ず付けるべきヘッダ。

⑤ Referrer-Policy - リファラ漏洩制御

外部サイトに遷移した時に Referer ヘッダで「どこから来たか」をどこまで伝えるかを制御します。プライバシーと機能性のバランスが論点。

Referrer-Policy: strict-origin-when-cross-origin

主な値:

挙動
no-referrer常にRefererを送らない(最強プライバシー、Analyticsで参照元不明に)
strict-origin-when-cross-origin同一オリジンならフルパス、別オリジンならオリジンのみ。現代ブラウザ既定かつ推奨
same-origin別オリジンには一切送らない
unsafe-url常にフルURLを送る(避けるべき)

URL にトークンやセッション ID が入る可能性があるなら、厳格な値にしてリファラ経由の漏洩を防ぐのが基本。

⑥ Permissions-Policy - ブラウザAPI制限

旧称 Feature-Policy。「カメラ・マイク・位置情報など機微なAPIを、このサイト/iframeから使用可能にするか」を宣言します。

Permissions-Policy:
  camera=(),
  microphone=(),
  geolocation=(),
  browsing-topics=(),
  interest-cohort=(),
  payment=(),
  usb=()

()(空)は「どこからも使用不可」の意味。本サイトは静的ツール集なので、これらのAPIを一切必要としないので全部閉じています。

特に注目すべき項目:

  • browsing-topics=() / interest-cohort=(): Google が推進した広告ターゲティング技術(Topics API / FLoC)を無効化。プライバシー視点では推奨
  • camera=() / microphone=(): 不要なら必ず無効化。XSS された時に勝手にカメラを起動される攻撃を防ぐ

⑦ X-DNS-Prefetch-Control - DNSプリフェッチ

X-DNS-Prefetch-Control: on

ページ内のリンク先ホスト名の DNS 解決を、ユーザーがクリックする前にブラウザに先回りさせる設定。セキュリティではなく速度のためのヘッダですが、securityheaders.com の評価項目に含まれているので合わせて設定します。

プライバシー重視なら off もあり(DNS クエリで興味関心が漏れる懸念)。本サイトは外部リンクが少ないので on でデフォルトの体験を優先しています。

「設定しない」べきヘッダもある

X-XSS-Protection(廃止)

昔は X-XSS-Protection: 1; mode=block が推奨されていましたが、ブラウザ側のヒューリスティックが脆弱性を生むことが判明し、Chromeは2020年に削除。無くてOK、CSPで防御

Server / X-Powered-By

サーバ実装情報を漏らすヘッダ(Server: nginx/1.18.0 など)。攻撃者にバージョン依存の脆弱性を狙う手がかりを与えるので、削除するのがベストプラクティス。Next.js は poweredByHeader: false で明示的に切れます。

Cookie のセキュリティ属性も合わせて

ヘッダ群とは別ですが、Cookie のセキュリティ属性も同じレイヤーで対策します。詳しくは HTTP Cookie Parser ツールで属性可視化できますが、要点は3つ:

  • Secure: HTTPS でのみ送信
  • HttpOnly: JS から読めない(XSS での Cookie 窃取を防止)
  • SameSite=Lax(または Strict): クロスサイトでの自動送信を制限(CSRF対策)

導入手順とテスト

どこに書くか:

  • Next.js: next.config.tsheaders()
  • Express: helmet ミドルウェア
  • Nginx / Apache: 各設定ファイルで add_header / Header set
  • Cloudflare / Vercel / Netlify: ダッシュボード or 設定ファイル

テストは2ステップ:

  1. securityheaders.com でグレード確認(A以上が目安)
  2. CSP Evaluator(Google)で CSP の弱点をピンポイント分析

どちらも無料。設定変更のたびにチェックする習慣を付けると、CSP デプロイ事故が減ります。

段階的導入のコツ

いきなり厳格なCSPを本番投入すると、サイトが壊れて顧客に迷惑をかける可能性があります。Report-Only モードから始めるのが定石:

Content-Security-Policy-Report-Only: ...

このヘッダはブロックせずに違反だけレポートさせる。1〜2週間運用してログを見て、本来許可すべきリソースを特定してから本番モードに切り替えます。

HSTS も同様に、max-age を最初は短く(数時間 → 数日 → 数ヶ月 → 2年)と段階的に伸ばすのが安全。

まとめ: 最小構成のテンプレート

新規サイトの初期設定として、最低限これを入れれば securityheaders.com で A評価を狙えます:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'unsafe-inline';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  object-src 'none';
  base-uri 'self';
  frame-ancestors 'none'

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()

7行のヘッダ追加で、XSS / クリックジャッキング / MIMEスニッフィング / リファラ漏洩 / 機微API濫用 / HTTPダウングレード 全てに対する基礎防御が成立します。

おわりに

セキュリティヘッダは「コード変更ほぼゼロで A 評価が取れる」コスパ最強の対策です。OWASP Top 10 の A05(Security Misconfiguration)を一発で改善できる、見過ごせない打ち手。

本サイトの HTTP Status Code ReferenceHTTP Cookie Parser で関連ヘッダの動作を確認できます。設定後は securityheaders.com でグレードチェックする習慣を付けてください。

関連: XSS の基礎と防御 / CSRF の仕組みと対策 / HTTPS と TLS の仕組み

Tool companion

この記事と一緒に使えるツール

Related reading

関連記事