.htaccess Generator

セキュリティヘッダー解説ガイド

ジェネレーター

Header set vs Header always set

ディレクティブ 適用範囲
Header set 成功レスポンス(200系)のみ
Header always set エラーレスポンス(403 / 404 等)にも付与

セキュリティヘッダーは Header always set を使う。エラーページでもブラウザに安全な動作を指示するため、always が必須。


HSTS(HTTP Strict Transport Security)

Header always set Strict-Transport-Security \
  "max-age=63072000; includeSubDomains; preload" \
  "expr=%{HTTPS} == 'on' || %{HTTP:X-Forwarded-Proto} == 'https'"

役割

ブラウザに「今後必ず HTTPS で接続してください」と宣言するヘッダー。

.htaccess の HTTPS リダイレクトはリクエストがサーバーに到達してからリダイレクトを行う。HSTS はブラウザ側で事前に HTTPS 化するため、中間者攻撃(MITM)のリスクをゼロにできる。

各パラメータの意味

パラメータ 意味
max-age=63072000 HSTS ポリシーを保持する期間(秒)。63072000 秒 = 2年
includeSubDomains サブドメインにも HSTS を適用する
preload ブラウザの HSTS プリロードリストへの登録を許可する(初回アクセスも HTTPS 化)

expr= 条件の役割(Nginx リバースプロキシ対応)

XServer・ConoHa WING などのレンタルサーバーは Nginx → Apache のリバースプロキシ構成を採用している。この場合、ユーザーが HTTPS でアクセスしてもサーバーの Apache は HTTP で受け取るため、%{HTTPS} だけでは判定できない。

ユーザー →(HTTPS)→ Nginx(TLS終端) →(HTTP)→ Apache

expr= 条件は Apache の式(Expression)評価エンジンを使い、HTTPS 接続または X-Forwarded-Proto: https のどちらかが成立する場合のみヘッダーを送信する。これにより HTTP アクセス時に HSTS ヘッダーが送られることを防ぐ。

includeSubDomains を有効にする前に、すべてのサブドメインが HTTPS に対応していることを確認する。対応していないサブドメインにアクセスできなくなる。


CSP(Content Security Policy)

Header always set Content-Security-Policy "upgrade-insecure-requests;"

upgrade-insecure-requests の役割

ページ内の http:// リソース(画像・CSS・JS など)を自動的に https:// に変換する指示。Mixed Content(HTTP と HTTPS が混在するページ)を自動修正するために使う。

ソースディレクティブの概要

CSP はリソースの読み込み元を制限するディレクティブを持つ。WordPress サイトに本格的な CSP を導入する場合は以下に注意が必要。

ディレクティブ 制限対象
default-src 他のディレクティブのフォールバック(指定がない場合に適用)
script-src JavaScript の読み込み元
style-src CSS の読み込み元
img-src 画像の読み込み元
font-src フォントの読み込み元
connect-src Ajax / Fetch / WebSocket の接続先

WordPress 固有の注意点

WordPress はコアと多くのプラグインがインラインスクリプト・eval() を使用するため、script-src'unsafe-inline''unsafe-eval' が必要になるケースが多い。CSP を強化する場合は nonce ベースの実装が推奨されるが、多くのプラグインとの互換性を維持するのは難しい。

img-src と OG image の落とし穴

img-src を明示すると default-src のフォールバックが効かなくなる。以下のミスに注意する。

# NG: 'self' を入れ忘れると自サイト画像もブロックされる
img-src data:

# OK: 必ず 'self' を含める
img-src 'self' data:

OG image(SNS シェア時に使われるサムネイル画像)もブロック対象になる。img-src を書くなら必ず 'self' を含める。

Report-Only モード

いきなり本番環境に CSP を適用するとサイトが壊れるリスクがある。まず Content-Security-Policy-Report-Only ヘッダーでテストし、違反レポートを確認してから本番適用するのが安全。

# テスト用(実際のブロックは行わず、違反をレポートのみ)
Header always set Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report"

Report-Only モードでは upgrade-insecure-requests は無視される。これはアクション指示(リソースのアップグレード)であり、制限指示ではないため。本番 CSP にのみ含める。


X-Content-Type-Options

Header always set X-Content-Type-Options "nosniff"

役割と防御対象

ブラウザが MIME タイプを自動推測(MIME スニッフィング)する機能を無効にするヘッダー。

MIME スニッフィングを悪用した攻撃として、画像ファイルに偽装した JavaScript をアップロードしてブラウザに実行させる XSS 攻撃がある。nosniff を指定すると、サーバーが返す Content-Type ヘッダーの値をブラウザが厳格に遵守するため、この攻撃を防げる。


X-Frame-Options

Header always set X-Frame-Options "SAMEORIGIN"

役割と防御対象

他サイトがこのサイトのページを <iframe> で埋め込むことを制限するヘッダー。クリックジャッキング攻撃を防止する。

クリックジャッキングとは、攻撃者が自分のサイトに対象サイトを透明な iframe で重ね、ユーザーに見えないボタンをクリックさせる攻撃手法。

設定値の意味

意味
SAMEORIGIN 同一オリジンからの埋め込みのみ許可(推奨)
DENY すべての埋め込みを禁止

Referrer-Policy

Header always set Referrer-Policy "strict-origin-when-cross-origin"

役割

リンクを踏んで他サイトに移動したとき、ブラウザが Referer ヘッダーにどれだけの情報を含めるかを制御するヘッダー。URL には管理画面のパスや個人情報を含む場合があり、外部サイトへの漏洩を防ぐ。

strict-origin-when-cross-origin の動作

移動先 送信内容
同一オリジン(自サイト内) 完全な URL(パスを含む)を送信
外部オリジン(https→https) オリジン部分のみ送信(https://example.com
外部オリジン(https→http) 何も送信しない

Permissions-Policy

Header always set Permissions-Policy \
  "camera=(), microphone=(), payment=(), usb=()"

役割

ブラウザが持つ強力な API(カメラ・マイク・決済など)の使用を制限するヘッダー。WordPress サイトで通常使用しないデバイス API を無効化することで、マルウェアや XSS 攻撃が不正にこれらの API を呼び出すことを防ぐ。

空の括弧 () はそのディレクティブを完全に無効化することを意味する(すべてのオリジンからの使用を禁止)。


防御マップ — 各ヘッダーの担当範囲

┌── HSTS ──────────── HTTP→HTTPS 強制(ブラウザレベル)
├── CSP ───────────── Mixed Content 自動修正 + リソース制限
├── X-Content-Type ── MIME 偽装による XSS 防止
├── X-Frame-Options ─ クリックジャッキング防止
├── Referrer-Policy ─ URL 情報の漏洩制御
└── Permissions ───── デバイス API の不正利用防止

これらのヘッダーはすべてレスポンスヘッダーとして mod_headers モジュールで出力する。<IfModule mod_headers.c> でラップすることで、モジュールが無効な環境でも 500 エラーを防げる。

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" "expr=%{HTTPS} == 'on' || %{HTTP:X-Forwarded-Proto} == 'https'"
    Header always set Content-Security-Policy "upgrade-insecure-requests;"
    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=(), payment=(), usb=()"
</IfModule>
← ジェネレーターに戻る