セキュリティヘッダーの設定方法|HSTS・CSPの設定例つき

この記事で分かること

  • HSTS、CSP、X-Frame-Optionsなど、主要なセキュリティヘッダーの役割と推奨値
  • Apache(.htaccess)、nginx、WordPressで使える設定コード
  • HSTSとCSPを、サイトを壊さずに入れる段階導入の手順
  • 設定の落とし穴と、curlや開発者ツールでの確認方法

要点は三つです。一つ目に、セキュリティヘッダーは「このページはこう扱ってほしい」というブラウザへの指示で、サーバー側の設定だけで追加できます。二つ目に、すぐ入れても問題が出にくいもの(X-Content-Type-Options、Referrer-Policyなど)と、段階導入が必要なもの(HSTS、CSP)があります。三つ目に、書いただけで終わらせず、実際の応答を見て確認します。

セキュリティヘッダーの種類と推奨値

セキュリティヘッダーは、Webサーバーが返すHTTP応答のヘッダーに含める、ブラウザ向けの安全上の指示です。最初に整えたい6種類を表にします。

ヘッダー役割推奨値の目安
Strict-Transport-Security以後はHTTPSだけで接続させるmax-age=31536000; includeSubDomains(段階的に導入)
Content-Security-Policy読み込める取得元を制限するサイトごとに設計(Report-Onlyから開始)
X-Frame-Options他サイトのフレーム内表示を禁じるSAMEORIGIN または DENY
X-Content-Type-Options内容からの種類の推測を禁じるnosniff
Referrer-Policy他サイトへ渡すURL情報を絞るstrict-origin-when-cross-origin
Permissions-Policyカメラや位置情報などの機能を制限するcamera=(), microphone=(), geolocation=()

注意:HSTSとCSPは、表の値を最初から入れないでください。後半の段階導入の手順で進めます。

Strict-Transport-Security(HSTS)

ブラウザに、そのドメインへは今後HTTPSだけで接続すると、一定期間覚えさせます。max-age は覚えておく秒数で、31536000は1年です。HSTSは、HTTPSの応答に付けたものだけが有効で、HTTPで返したヘッダーはブラウザに無視されます(MDN)。仕様はRFC 6797です。

includeSubDomains を付けると、すべてのサブドメインが対象です。HTTPSに対応していないサブドメインは接続できなくなるため、確認してから付けます。preload は、ブラウザに組み込まれる一覧へ登録する前提の指定で、取り消しに時間がかかります。必要性が明確になるまでは付けません。

Content-Security-Policy(CSP)

読み込んでよいスクリプト、画像、フレームなどの取得元を、サイト側が宣言します。XSSで外部スクリプトが差し込まれても、許可していない取得元のものは実行されないため、被害を小さくできます。一方で、サイトが使う外部サービス(アクセス解析、広告、地図、動画の埋め込みなど)を洗い出す必要があり、6種類のうち最も導入に手間がかかります。詳しくはCSPの用語解説と、後半の段階導入で扱います。

X-Frame-Options

他のサイトが、自サイトを <iframe> の中に表示することを禁じ、クリックジャッキングを防ぎます。値は、どこからの埋め込みも禁じる DENY と、同じオリジンだけ許す SAMEORIGIN です。ALLOW-FROM は現在のブラウザが無視するため、使えません。

新しい方式は、CSPの frame-ancestors です。古いブラウザも考えて、両方を併記しても構いません。frame-ancestors は、metaタグでは効かず、HTTPヘッダーで送る必要があります。用語解説もあります。

X-Content-Type-Options

値は nosniff だけです。ブラウザがファイルの内容から種類を推測し(スニッフィング)、画像として置いたファイルをスクリプトとして実行する、といった挙動を止めます。Content-Type が正しく返っていることが前提です。用語解説

Referrer-Policy

他のサイトへ移動するとき、元のページのURLをどこまで伝えるかを決めます。指定がない場合、近年のブラウザは strict-origin-when-cross-origin を既定にしますが、ブラウザによる差をなくすため、明示します。URLに会員番号などを載せているサイトでは、no-referrer や same-origin も検討します。用語解説

Permissions-Policy

カメラ、マイク、位置情報など、ブラウザの機能を使えるページや埋め込み先を絞ります。サイトが使わない機能は、空の許可リスト () で無効にします。以前の Feature-Policy の後継で、書き方が違います。用語解説

付けなくてよいヘッダーと、消したいヘッダー

X-XSS-Protection は、現在のブラウザでは役割を終えています。OWASPのチートシートは、付けないか、付けるなら 0 にするよう勧めています。ServerやX-Powered-Byに、ApacheやPHPの版が出ている場合は、取り除きます。攻撃者に手がかりを与えないための処置で、脆弱性そのものを直すものではありません。

設定コード:Apache・nginx・WordPress

HTTPSで配信しているサイトの設定例です。HSTSの期間は、最初は300秒にしてあります。段階導入の手順に沿って延ばしてください。

Apache(.htaccess)

<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=300"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always unset X-Powered-By
</IfModule>

mod_headersが有効なサーバーで動きます。無効だと、<IfModule> の中身は黙って無視されます。always は、404や500などのエラー応答にもヘッダーを付ける指定です。付けないと、成功した応答だけが対象です(mod_headersの公式文書)。Serverヘッダーの版表記を減らす ServerTokens Prod は、サーバー全体の設定で、.htaccessでは指定できません。

nginx

server_tokens off;
add_header Strict-Transport-Security "max-age=300" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

HTTPSの server ブロックに書きます。変更後は nginx -t で構文を確認してから、reloadします。always がないと、200や301などの応答にしか付かず、404や500には付きません(nginxの公式文書)。location の中に別の add_header がある場合の落とし穴は、後半で説明します。

WordPress

WordPressの公式フィルター wp_headers で、WordPressが返す応答にヘッダーを足せます。子テーマの functions.php か、小さな専用プラグインに書きます。親テーマに書くと、テーマの更新で消えます。

add_filter( 'wp_headers', function ( $headers ) {
    $headers['X-Content-Type-Options'] = 'nosniff';
    $headers['X-Frame-Options']        = 'SAMEORIGIN';
    $headers['Referrer-Policy']        = 'strict-origin-when-cross-origin';
    $headers['Permissions-Policy']     = 'camera=(), microphone=(), geolocation=()';
    return $headers;
} );

注意:この方法で付くのは、WordPressが生成するページの応答だけです。画像やCSSなどの静的ファイルは、WordPressを通らないため対象になりません。サイト全体に付けたい場合や、HSTSを付ける場合は、前述のサーバー設定で行います。

HSTSとCSPの段階導入

HSTSは期間を少しずつ延ばす

  1. 全ページと、使っているすべてのサブドメインが、HTTPSで表示されることを確認します。
  2. max-age=300(5分)で配信し、全ページで表示や証明書の警告に問題がないか確かめます。
  3. max-age=604800(1週間)、max-age=2592000(1か月)と延ばします。前の期間が過ぎるのを待ってから、次へ進みます。
  4. 問題がなければ max-age=31536000(1年)にします。全サブドメインがHTTPSだと確認できた場合に限り、includeSubDomains を足します。

この手順は、hstspreload.orgの推奨に沿っています。

CSPはReport-Onlyから始める

最初は、ブロックせず違反だけを報告する Content-Security-Policy-Report-Only で配信します。

Header always set Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; base-uri 'self'; form-action 'self'"
  1. ページを巡回し、開発者ツールのConsoleに出る [Report Only] の違反表示を集めます。
  2. アクセス解析、フォント、地図、動画、問い合わせフォームなど、正当な取得元を許可リストに足します。
  3. 違反が出なくなったら、ヘッダー名を Content-Security-Policy に変えて、強制に切り替えます。
  4. インラインのスクリプトが多い場合は、外部ファイルへ移すか、nonceやハッシュで許可します。'unsafe-inline' はXSS対策の効果を大きく損なうため、避けられるなら避けます。

違反の報告をサーバーに集めたい場合は、report-to と Reporting-Endpoints ヘッダーを使います。設定例はMDNにあります。

よくある失敗と落とし穴

  • always の付け忘れ。付けないと、404や500のエラーページにヘッダーが出ません。表示崩れの確認も、エラーページまで行います。
  • nginxのadd_headerの継承。下位の location に add_header が1つでもあると、上位の指定は全て外れます。nginx 1.29.3以降は add_header_inherit merge; で足し合わせられます。
server {
    add_header X-Content-Type-Options "nosniff" always;

    location /assets/ {
        add_header Cache-Control "public, max-age=2592000";
    }
}
  • ヘッダーの二重化。アプリとサーバーの両方が同じヘッダーを返したり、Apacheで Header add を使ったりすると、同名のヘッダーが2つ並びます。ブラウザの解釈が割れるため、set で上書きします。
  • CSPで外部サービスが止まる。アクセス解析、広告、チャット、問い合わせフォームが動かなくなることがあります。Report-Onlyの期間で洗い出します。
  • HSTSで、証明書の更新漏れが致命傷になる。HSTSが有効だと、証明書エラーの警告を、利用者は回避して進めません。更新の自動化と期限の監視を先に整えます。
  • CDNやキャッシュによる上書き。サーバーでは正しく設定していても、CDNが除去や上書きをすることがあります。確認は、外から実際の応答で行います。
  • metaタグでは効かない。X-Frame-Optionsと frame-ancestors は、HTMLのmetaタグに書いても無効です。HTTPヘッダーで送ります。

設定できたかを確認する方法

設定ファイルに書いただけでは、付いたかどうかは分かりません。外から実際の応答を見ます。

curlで確認する

curl -I https://example.com/
curl -s -D - -o /dev/null https://example.com/

1行目はHEADリクエストで、ヘッダーだけを取得します。2行目はGETの応答ヘッダーを表示します。HEADに別の応答を返すサーバーでは、2行目のほうが実際の配信に近い結果になります。存在しないURLにも同じ確認をして、404の応答にヘッダーが付いているかも見ます。

ブラウザの開発者ツールで確認する

ChromeやEdgeでは、F12キーで開発者ツールを開き、Networkタブでページを再読み込みします。一覧の先頭にある文書の行を選び、HeadersのResponse Headersを見ます。CSPの違反は、Consoleタブに出ます。

一括して確かめたい場合は、Security Checker XにURLを入力すると、ここで扱ったヘッダーの有無と値、Cookie、証明書までを診断できます。登録は不要です。

よくある質問

セキュリティヘッダーは、検索順位に影響しますか?

これらのヘッダーが検索順位の要因だと、公式に示された事実はありません。一方で、設定を誤って表示や機能が壊れれば、利用者の離脱につながります。段階導入と確認が大切です。

.htaccessに書いたのに、反映されません。何を確認すればよいですか?

次の順に確認します。サーバーがApacheか(nginxは.htaccessを読みません)、mod_headersが有効か、サーバー側で.htaccessの上書きが許可されているか、CDNやキャッシュが古い応答を返していないか。WordPressの場合は、WordPressが書き換える範囲の外に書いているかも見ます。

nginxでserverブロックに書いたのに、一部のURLだけ付きません。

そのURLに当たるlocationブロックの中に、別のadd_headerがある可能性が高いです。add_headerは、下位のブロックに1つでもあると、上位の指定を引き継ぎません。下位のブロックにも同じ指定を書くか、nginx 1.29.3以降のadd_header_inheritを使います。

X-Frame-OptionsとCSPのframe-ancestorsは、どちらを使えばよいですか?

新しい方式はframe-ancestorsです。古いブラウザも考えて、X-Frame-Optionsを併記しても構いません。どちらも、metaタグでは効かず、HTTPヘッダーで送る必要があります。

HSTSをやめて、HTTPに戻したいときはどうしますか?

HTTPSの応答で、max-age=0を返します。ブラウザは、次にHTTPSで接続したときに記憶を消します。ヘッダーを外すだけでは、記憶が期限まで残ります。preloadの一覧に登録済みの場合は、別途削除の手続きが必要で、反映に数か月かかることがあります。

レンタルサーバーでも設定できますか?

多くの場合、できます。.htaccessが使える環境ならApacheの例をそのまま使えます。管理画面にヘッダーの設定欄がある場合や、CloudflareなどのCDNでレスポンスヘッダーを追加できる場合もあります。

まとめ

最初に、X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policyの4つを入れます。HSTSは短い期間から延ばし、CSPはReport-Onlyで影響を見てから強制に切り替えます。どの段階でも、設定後は実際の応答で確かめてください。確認項目の全体像は、Webサイトのセキュリティチェック項目一覧にまとめています。

運用中のサイトへの導入では、影響範囲の見極めが難しいことがあります。設定の代行や、導入後の保守は、ホームページの制作・保守のご相談からお問い合わせください。

よくある質問

セキュリティヘッダーは、検索順位に影響しますか?

これらのヘッダーが検索順位の要因だと、公式に示された事実はありません。一方で、設定を誤って表示や機能が壊れれば、利用者の離脱につながります。段階導入と確認が大切です。

.htaccessに書いたのに、反映されません。何を確認すればよいですか?

次の順に確認します。サーバーがApacheか(nginxは.htaccessを読みません)、mod_headersが有効か、サーバー側で.htaccessの上書きが許可されているか、CDNやキャッシュが古い応答を返していないか。WordPressの場合は、WordPressが書き換える範囲の外に書いているかも見ます。

nginxでserverブロックに書いたのに、一部のURLだけ付きません。

そのURLに当たるlocationブロックの中に、別のadd_headerがある可能性が高いです。add_headerは、下位のブロックに1つでもあると、上位の指定を引き継ぎません。下位のブロックにも同じ指定を書くか、nginx 1.29.3以降のadd_header_inheritを使います。

X-Frame-OptionsとCSPのframe-ancestorsは、どちらを使えばよいですか?

新しい方式はframe-ancestorsです。古いブラウザも考えて、X-Frame-Optionsを併記しても構いません。どちらも、metaタグでは効かず、HTTPヘッダーで送る必要があります。

HSTSをやめて、HTTPに戻したいときはどうしますか?

HTTPSの応答で、max-age=0を返します。ブラウザは、次にHTTPSで接続したときに記憶を消します。ヘッダーを外すだけでは、記憶が期限まで残ります。preloadの一覧に登録済みの場合は、別途削除の手続きが必要で、反映に数か月かかることがあります。

レンタルサーバーでも設定できますか?

多くの場合、できます。.htaccessが使える環境ならApacheの例をそのまま使えます。管理画面にヘッダーの設定欄がある場合や、CloudflareなどのCDNでレスポンスヘッダーを追加できる場合もあります。

関連記事

関連する用語

サイトの設定を無料で確認する

この記事の内容を、自分のサイトで確かめたい時は、Webサイト セキュリティチェッカー「Security Checker X」をお使いください。URLを入力するだけで、登録なしで診断できます。

デジタルマーケティング事業部 統括マネージャー

略歴:京都大学情報学研究科知能情報学専攻修士課程修了後、日経大手インターネットショッピングモールの開発部でエンジニアとしてシステム開発・運用に従事。同社新規モバイル事業の立ち上げに開発プロジェクトマネージャー、兼プロダクトマネージャーとして参画。その後、外資系大手製薬メーカーのデジタルマーケティング部門でシニアアソシエイトとして従事した後、2020年にエスライン・テクノロジーズのデジタルマーケティング事業部統括マネージャーに就任。カスタマーファーストでデジタルマーケティングの役立つ情報を日々発信中。

コメント

この記事へのトラックバックはありません。

【MALINE】総合デジタルマーケティングツール
【特別価格】Digicert VMC
NEWS
  1. 1

    【NEWS】旅行比較サイト『TRAVEL HUB(トラベルハブ)』サービス提供開始のお知らせ

  2. 2

    オフィス移転のお知らせ

  3. 3

    【MALINE】マリン株式会社設立のお知らせ

  4. 4

    無料で使える「Excel版 一斉メール配信ツール」提供開始のお知らせ ~SMTP設定だけで今すぐメール一括送信~

  5. 5

    中小企業向けDXプラットフォーム『Hirameki 7』SEO/MEO支援オプション提供開始。Hirameki 7ご利用者様の集客効果を最大化!

カレンダーから記事を探す
2026年10月
月 火 水 木 金 土 日
 1234
567891011
12131415161718
19202122232425
262728293031  
SEO検索順位チェッカー
Googleマップ/MEO順位チェックツール
【無料】メールアドレス生存確認ツール
【無料】Excel一斉メール送信ツール
メールアドレス漏洩・流出チェックツール
メールドメインブラックリスト判定ツール
DMARC/SPF/DKIM診断ツール
IPアドレス位置・住所特定ツール
自分のIPアドレス確認ツール
驚愕効果のSEO対策

関連記事