Webサーバーがブラウザに返すHTTPレスポンスには、コンテンツだけでなくセキュリティ設定を伝えるヘッダーを含められます。これらを適切に設定することで、クリックジャッキング・コンテンツスニッフィング・情報漏洩などの攻撃を防げます。
なぜセキュリティヘッダーが必要か
コードに脆弱性がなくても、ブラウザの動作をサーバー側でコントロールしないと攻撃者に悪用される余地が残ります。セキュリティヘッダーはブラウザに対して「このサイトでどう振る舞うべきか」を指示する仕組みです。
WordPressサイトや静的サイトでも、.htaccess 数行の追記で有効にできます。
主要なセキュリティヘッダー7種
1. Strict-Transport-Security(HSTS)
HTTPS接続を強制するヘッダーです。一度訪問したブラウザに「次回以降も必ずHTTPSで接続せよ」と伝え、HTTP→HTTPSのリダイレクト前にデータが平文で流れるリスクを排除します。
| パラメータ | 意味 |
|---|---|
max-age | HTTPS強制を記憶する秒数(31536000=1年) |
includeSubDomains | サブドメインにも適用 |
preload | ブラウザのHSTSプリロードリストへの登録申請時に必要 |
注意: HSTSを設定したあとHTTPに戻すとブラウザがアクセスできなくなります。SSL証明書の維持が前提です。
2. X-Frame-Options
クリックジャッキング攻撃を防ぐヘッダーです。自サイトを <iframe> で読み込めるサイトを制限します。
| 値 | 意味 |
|---|---|
DENY | どこからのiframe読み込みも禁止 |
SAMEORIGIN | 同一オリジンからのみ許可 |
クリックジャッキングとは、透明なiframeで正規サイトを覆い、ユーザーが意図しないボタンをクリックさせる攻撃です。ボタン1つで意図せず退会・送金・権限付与させられる被害が起きえます。
3. X-Content-Type-Options
ブラウザがMIMEタイプを推測して実行する動作(スニッフィング) を禁止します。
X-Content-Type-Options: nosniff
nosniff のみ有効な値です。たとえばサーバーが text/plain と宣言したファイルをブラウザがJavaScriptと判断して実行してしまうリスクを防ぎます。
4. Referrer-Policy
別サイトへのリンクをクリックした際、どこまでのURL情報を Referer ヘッダーで送るかを制御します。
| 値 | 送信される情報 |
|---|---|
no-referrer | 一切送信しない |
origin | オリジン(ドメイン)のみ |
strict-origin-when-cross-origin | 同一オリジンは完全URL、外部はオリジンのみ(推奨) |
unsafe-url | 常に完全URLを送信(非推奨) |
URLにセッションIDや個人情報が含まれるサイトでは、外部サイトへの漏洩を防ぐために設定が重要です。
5. Permissions-Policy(旧 Feature-Policy)
カメラ・マイク・位置情報などのブラウザAPIへのアクセス権限を制御します。
Permissions-Policy: camera=(), microphone=(), geolocation=()
() は「誰にも許可しない」を意味します。使用しない機能は明示的に無効化しておくことで、埋め込んだサードパーティスクリプトによる悪用を防げます。
6. Content-Security-Policy(CSP)
読み込めるリソースのオリジンを制限する強力なヘッダーです。XSS(クロスサイトスクリプティング)攻撃の被害を大幅に軽減できます。設定が複雑なため別記事で詳しく解説しています。
7. X-XSS-Protection
古いブラウザ向けのXSSフィルターを有効にするヘッダーです。現代のブラウザはこの設定を無視するか、CSPを優先します。
X-XSS-Protection: 1; mode=block
注意: 1; mode=block は一部の古いブラウザで逆にXSS脆弱性を生むことが知られています。CSPが設定済みであれば不要です。
.htaccessへの設定例
Apacheサーバー(さくら・エックスサーバー・ロリポップなど)では .htaccess に以下を追記します。
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>
## 現在の設定を確認する方法
ブラウザの開発者ツール(F12)→「ネットワーク」タブ→ページのリクエストを選択→「レスポンスヘッダー」で確認できます。
各ヘッダーが設定されているか、値が正しいかをまとめてチェックしたい場合はセキュリティヘッダー確認ツールが便利です。スコアと改善アドバイスを一覧で表示します。