HTTPセキュリティヘッダーとは:HSTS・CSPなどの役割と設定
HSTS・CSP・X-Frame-Options・Referrer-Policy・Permissions-Policyの役割と推奨値を解説。「要確認」と判定されたヘッダーが必ずしも弱点ではない理由も分かります。
セキュリティヘッダーとは
HTTPレスポンスは、どれもヘッダーから始まります。ヘッダーは Content-Type: text/html のような名前と値の組です。そのうちのいくつかは、ブラウザがページをどう扱うかを変えます。送信にコストはかからず、すべての訪問者に適用され、ページのHTMLではなく、サーバー、ホスティングプラットフォーム、またはコンテンツ配信ネットワーク(CDN)で設定します。
IPNixaは自サイトのヘッダーを _headers ファイルで設定しており、Cloudflareがすべてのページと一緒に配信しています。このサイトのチェッカーは、入力されたアドレスに当社のサーバーからリクエストし、リダイレクトを最大3回までたどって、最終的なレスポンスのヘッダーを読み取ります。
特に重要な6つのヘッダー
チェッカーが判定するのは次のヘッダーです。示した値は一般的で安全な出発点なので、サイトの要件に合わせて調整してください。
| ヘッダー | 防げること | 代表的な値 |
|---|---|---|
| Strict-Transport-Security (HSTS) | 初回アクセス以降に、接続が暗号化されないHTTPへ格下げされること | max-age=31536000; includeSubDomains |
| Content-Security-Policy (CSP) | 注入されたスクリプトの実行(クロスサイトスクリプティングの被害を抑えます) | default-src 'self'; script-src 'self'; frame-ancestors 'none' |
| X-Frame-Options または CSP frame-ancestors | 他サイトが見えないフレーム内にページを読み込むこと(クリックジャッキング) | DENY、または frame-ancestors 'none' |
| X-Content-Type-Options | ブラウザがファイルの種類を推測し、データをスクリプトとして実行すること | nosniff |
| Referrer-Policy | パスやクエリ文字列を含むページの完全なアドレスが、他サイトに漏れること | strict-origin-when-cross-origin |
| Permissions-Policy | ページや埋め込まれたフレームが、カメラ、マイク、位置情報を使うこと | camera=(), microphone=(), geolocation=() |
IPNixaのチェッカーによる各ヘッダーの判定基準
各ヘッダーは「あり」「要確認」「提供なし」の3つの状態のいずれかで判定されます。「要確認」は、ヘッダーはあるものの、その値が以下の基準を満たしていないことを意味します。詳しく確認するきっかけであり、セキュリティの点数ではありません。
- HSTS:1回だけ送られ、max-age が15552000秒(180日)以上であれば「あり」です。それより短い max-age や0は「要確認」になります。
- CSP:script-src または default-src でスクリプトを制御し、ポリシー内のどこにも 'unsafe-inline'、'unsafe-eval'、単独の * を含まない場合に「あり」です。報告のみ(report-only)のポリシーは何もブロックしないため、「提供なし」として扱います。
- フレーム制御:frame-ancestors ディレクティブが 'none'、'self'、または特定のアドレスに限定されている場合、または X-Frame-Options が DENY か SAMEORIGIN の場合に「あり」です。
- X-Content-Type-Options:値が nosniff の場合にのみ「あり」です。
- Referrer-Policy:最後の値が no-referrer、same-origin、strict-origin、strict-origin-when-cross-origin のいずれかであれば「あり」です。ブラウザは理解できる最後の値を使うため、複数の値が並んでいる場合は最後の値で判定します。
- Permissions-Policy:送られていれば「あり」です。どの機能を列挙すべきかはサイトによって異なるためです。
実際のサイトが送るヘッダー:サンプル調査
2026年11月2日、チェッカーと同じユーザーエージェントで5つのサイトのトップページにリクエストし、レスポンスをIPNixaの判定ルールで評価しました。ヘッダーは頻繁に変わるため、この時点のスナップショットとしてご覧ください。
| サイト | HSTS | CSP | フレーム制御 | nosniff | Referrer | Permissions |
|---|---|---|---|---|---|---|
| github.com | あり | 要確認 | あり | あり | あり | 提供なし |
| ipnixa.com | あり | 要確認 | あり | あり | あり | あり |
| www.wikipedia.org | あり | 提供なし | 提供なし | 提供なし | 提供なし | 提供なし |
| www.google.com | 提供なし | 報告のみ | あり | 提供なし | 提供なし | 提供なし |
| example.com | 提供なし | 提供なし | 提供なし | 提供なし | 提供なし | 提供なし |
サンプルの読み方:「要確認」は「弱い」という意味ではない
GitHubのポリシーは、スクリプトの読み込み元を自社のアセット用ホストと特定のハッシュに限定しており、厳格です。「要確認」となったのは、style-src が 'unsafe-inline' を許可しており、判定ルールがこのキーワードをポリシー全体から探すためにすぎません。インラインスタイルのリスクはインラインスクリプトよりはるかに小さいため、これは穴ではなく意図的なトレードオフです。
当サイトも「要確認」ですが、理由は異なります。ポリシーに含まれるのは frame-ancestors 'none' だけで、フレーム表示は防ぎますが、スクリプトは制限していません。結果はそのまま掲載しています。
Googleのトップページは、スクリプトのポリシーを Content-Security-Policy-Report-Only として送っており、違反を報告するだけでブロックはしません。また、このレスポンスではHSTSを送っていませんでした。大規模サイトは、ブラウザのプリロードリストなど別の方法でHTTPSを強制できます。Wikipediaのポータルは非常に長いHSTSの max-age を送っていますが、そのページではほかのヘッダーをほとんど送っていません。これらの結果から、各サイトが全体として安全かどうかは分かりません。分かるのは、それぞれのレスポンスがどのブラウザ側の保護を求めているかです。
自分のサイトにヘッダーを追加する
ヘッダーは1つずつ追加します。追加するたびにサイトを再読み込みし、ページ、ログイン、埋め込み動画、決済フォームが正常に動作することを確認してから次へ進んでください。
- まずはリスクの低いヘッダーから始めます。X-Content-Type-Options: nosniff、Referrer-Policy: strict-origin-when-cross-origin、そして X-Frame-Options: DENY です(ページを他サイトのフレーム内に表示させる必要がある場合を除きます)。
- HSTSは、まず300のような短い max-age で追加し、すべてのサブドメインがHTTPSで動作することを確認してから 31536000 に引き上げます。includeSubDomains は、すべてのサブドメインがHTTPSに対応している場合にだけ追加してください。
- Content-Security-Policy を作成し、最初は Content-Security-Policy-Report-Only として送ります。違反レポートを収集するかブラウザのコンソールを確認し、正当な読み込み元を修正または許可してから、実際にブロックするヘッダーに切り替えます。
- 使わない強力な機能を列挙した Permissions-Policy を追加します。例:camera=(), microphone=(), geolocation=()
- nginxでは always フラグを付けた add_header、Apacheでは Header always set を使います。静的ホスティングやCDNでは、各プラットフォームのヘッダー設定ファイルやレスポンスヘッダーのルールを使います。
- IPNixaのヘッダー確認をもう一度実行します。不足しているヘッダーごとに、nginx、Apache、_headers ファイル用にそのままコピーできる設定行が表示されます。
HSTSプリロードとその他の注意点
HSTSプリロードリストはブラウザに組み込まれているため、初回アクセスからHTTPSが使われます。ドメインを登録するには、1年以上の max-age、includeSubDomains、preload ディレクティブが必要で、リストからの削除がユーザーに反映されるまでには数か月かかります。社内向けのものも含め、すべてのサブドメインがHTTPSを使い続ける場合にだけ申請してください。
X-XSS-Protection は廃止されています。現在のブラウザはこれを無視し、CSPがその役割を引き継いでいます。クロスオリジン分離のためのヘッダー(Cross-Origin-Opener-Policy、Cross-Origin-Embedder-Policy、Cross-Origin-Resource-Policy)はチェッカーの判定対象外です。共有メモリなどの機能を使うサイトでのみ必要で、有効にすると第三者のコンテンツの埋め込みがブロックされることがあるためです。
よくある質問
ヘッダーがないサイトは、閲覧すると危険ですか?
いいえ。ヘッダーは、特定の攻撃に対するブラウザ側の防御を追加するものです。ヘッダーがなくても適切に運用されているサイトはありますし、すべてそろっていても別の欠陥を抱えている場合があります。結果は訪問者向けの判定ではなく、サイト管理者向けのチェックリストとして使ってください。
チェッカーで見えなかったヘッダーがブラウザに表示されるのはなぜですか?
サイトは、ページ、国、ログイン状態、CDNの拠点によってヘッダーを変えることがあります。チェッカーが読み取るのは、入力したアドレスに対する1回分のレスポンスで、CookieなしでCloudflareのネットワークから取得したものです。
X-Frame-Optionsとframe-ancestorsのどちらを使うべきですか?
CSPの frame-ancestors が現在の標準的な制御方法で、特定のサイトだけを許可することもできます。あわせて X-Frame-Options も送れば、古いブラウザにも対応できます。両方がある場合、現在のブラウザは frame-ancestors に従います。
ログインが必要なページも確認できますか?
いいえ。チェッカーはCookieや認証情報を送らず、プライベートアドレスやローカルアドレスへのリクエストも拒否します。ログインが必要なページやプライベートネットワーク上のページは、ブラウザの開発者ツールまたは curl -I で取得した生のレスポンスヘッダーをコピーし、チェッカーに貼り付けてください。貼り付けたヘッダーはブラウザ内で分析されます。