Webアプリケーションのセキュリティを強化する上で、HTTPセキュリティヘッダーの適切な設定は欠かせません。これらのヘッダーは、XSS攻撃、クリックジャッキング、MIMEスニッフィング攻撃などの脅威からユーザーを保護する重要な防御層として機能します。
この記事では、主要なセキュリティヘッダーであるContent-Security-Policy(CSP)、Strict-Transport-Security(HSTS)、X-Frame-Options、X-Content-Type-Optionsについて、それぞれの役割、設定方法、そしてNginx・Apache・Express.jsでの実装例を解説します。
セキュリティヘッダーが必要な理由
セキュリティヘッダーは、HTTPレスポンスに含まれるヘッダーで、ブラウザに対してセキュリティに関する指示を与えます。これにより、アプリケーションコードに脆弱性があった場合でも、ブラウザレベルで攻撃を防ぐことができます。
セキュリティヘッダーの役割
sequenceDiagram
participant Browser as ブラウザ
participant Server as サーバー
Browser->>Server: HTTPリクエスト
Server-->>Browser: HTTPレスポンス<br>+ セキュリティヘッダー
Note over Browser: ブラウザがセキュリティポリシーを適用<br>・インラインスクリプトのブロック(CSP)<br>・HTTPS通信の強制(HSTS)<br>・iframe埋め込みの制限(X-Frame-Options)<br>・MIMEタイプスニッフィングの防止主要なセキュリティヘッダー一覧
| ヘッダー名 | 主な目的 |
|---|---|
| Content-Security-Policy | XSS攻撃・データインジェクション攻撃の防止 |
| Strict-Transport-Security | HTTPS通信の強制 |
| X-Frame-Options | クリックジャッキング攻撃の防止 |
| X-Content-Type-Options | MIMEスニッフィング攻撃の防止 |
| Referrer-Policy | リファラー情報の漏洩防止 |
| Permissions-Policy | ブラウザ機能へのアクセス制御 |
Content-Security-Policy(CSP)の設定
Content-Security-Policy(CSP)は、Webページで読み込み可能なリソースの出所を制限するセキュリティヘッダーです。XSS攻撃やデータインジェクション攻撃に対する強力な防御機能を提供します。
CSPの基本構文
CSPは1つ以上のディレクティブで構成され、各ディレクティブはリソースの種類と許可する出所を指定します。
Content-Security-Policy: <ディレクティブ> <値>; <ディレクティブ> <値>
主要なCSPディレクティブ
| ディレクティブ | 説明 |
|---|---|
default-src |
他のディレクティブで指定されていないリソースのデフォルトポリシー |
script-src |
JavaScriptの読み込み元を制限 |
style-src |
CSSの読み込み元を制限 |
img-src |
画像の読み込み元を制限 |
font-src |
Webフォントの読み込み元を制限 |
connect-src |
fetch、XMLHttpRequest、WebSocketの接続先を制限 |
frame-src |
iframe内に読み込めるコンテンツを制限 |
frame-ancestors |
当該ページをiframeで埋め込める親ページを制限 |
form-action |
フォームの送信先を制限 |
base-uri |
<base>要素で指定できるURLを制限 |
object-src |
<object>、<embed>、<applet>要素のソースを制限 |
CSPのソース値
ディレクティブには以下のソース値を指定できます。
| ソース値 | 説明 |
|---|---|
'self' |
同一オリジンからのリソースのみ許可 |
'none' |
すべてのリソースを拒否 |
'unsafe-inline' |
インラインスクリプト・スタイルを許可(非推奨) |
'unsafe-eval' |
eval()などの動的コード実行を許可(非推奨) |
'strict-dynamic' |
nonceまたはhashで信頼されたスクリプトが動的に読み込むスクリプトを許可 |
'nonce-<値>' |
指定されたnonceを持つスクリプト・スタイルのみ許可 |
'sha256-<ハッシュ>' |
指定されたハッシュ値に一致するスクリプト・スタイルのみ許可 |
https: |
HTTPS経由のリソースのみ許可 |
data: |
dataスキームのリソースを許可 |
*.example.com |
特定ドメインからのリソースを許可 |
CSPの設定例
以下は、実践的なCSP設定の例です。
基本的なCSP設定
|
|
この設定では以下のポリシーが適用されます。
- すべてのリソースは同一オリジンからのみ読み込み可能
- 画像はdataスキーム(Base64画像)も許可
- iframeへの埋め込みを禁止
- プラグインコンテンツを完全に禁止
nonce方式を使用したCSP設定
インラインスクリプトを使用する場合は、nonce方式を採用することで安全に許可できます。
|
|
HTML側では、許可するスクリプトにnonce属性を付与します。
|
|
nonce値はリクエストごとに一意で予測不可能な値を生成する必要があります。
Report-Onlyモードでのテスト
CSPの導入時には、まずReport-Onlyモードで動作を確認することを推奨します。
|
|
このモードでは、ポリシー違反があってもリソースはブロックされず、レポートのみが送信されます。
CSP違反レポートの設定
CSP違反が発生した際にレポートを受け取る設定を追加できます。
|
|
レポートはJSON形式で以下のような情報が含まれます。
|
|
Strict-Transport-Security(HSTS)の設定
Strict-Transport-Security(HSTS)は、ブラウザに対してHTTPS通信のみを使用するよう指示するセキュリティヘッダーです。中間者攻撃(MITM攻撃)やSSLストリッピング攻撃を防止します。
HSTSの基本構文
Strict-Transport-Security: max-age=<秒数>; includeSubDomains; preload
HSTSのディレクティブ
| ディレクティブ | 説明 |
|---|---|
max-age |
ブラウザがHTTPS接続を記憶する期間(秒単位) |
includeSubDomains |
サブドメインにもHSTSポリシーを適用 |
preload |
ブラウザのプリロードリストへの登録を希望 |
HSTSの動作
sequenceDiagram
participant Browser as ブラウザ
participant Server as サーバー
Note over Browser,Server: 1. 初回アクセス(HTTPでアクセスした場合)
Browser->>Server: http://example.com
Server-->>Browser: 301 → https://...
Note over Browser,Server: 2. HTTPSでの接続
Browser->>Server: https://example.com
Server-->>Browser: + HSTS ヘッダー
Note over Browser: ブラウザがHSTSを記憶
Note over Browser,Server: 3. 以降のアクセス(HTTPを指定しても自動でHTTPSに)
Note over Browser: http://example.com<br>→ 内部変換 →<br>https://example.com
Browser->>Server: https://example.comHSTSの設定例
推奨される設定
OWASPが推奨する設定では、max-ageを2年(63072000秒)に設定します。
|
|
段階的な導入
HSTSを初めて導入する場合は、短いmax-ageから始めて徐々に延長することを推奨します。
|
|
HSTSプリロードリスト
HSTSプリロードリストは、ブラウザに事前に登録されたHSTS対応サイトのリストです。これに登録されると、ユーザーが初めてサイトにアクセスする前からHTTPS接続が強制されます。
プリロードリストへの登録はhstspreload.orgで申請できます。登録には以下の要件を満たす必要があります。
- 有効なSSL/TLS証明書を持っていること
- すべてのサブドメインでHTTPSが有効であること
max-ageが31536000秒(1年)以上であることincludeSubDomainsとpreloadディレクティブが含まれていること
HSTSの注意点
HSTSを有効にする前に、以下の点を確認してください。
- すべてのサブドメインがHTTPS対応していること(
includeSubDomains使用時) - SSL/TLS証明書の有効期限切れに注意すること
- 一度設定すると
max-age期間中はHTTP通信に戻せないこと - プリロードリストからの削除には時間がかかること
X-Frame-Optionsの設定
X-Frame-Optionsは、ページをiframe、frame、embed、objectタグ内で表示することを制御するセキュリティヘッダーです。クリックジャッキング攻撃を防止します。
クリックジャッキング攻撃とは
flowchart TB
subgraph AttackerPage["攻撃者のページ"]
subgraph TransparentIframe["透明なiframe(被害者サイト)"]
RealButton["送金実行ボタン<br>← 実際のクリック対象"]
end
FakeButton["景品をGET!<br>← ユーザーに見えるボタン"]
end
User((ユーザー)) -->|クリック| FakeButton
FakeButton -.->|実際にクリックされる| RealButton
Note["ユーザーは『景品をGET!』をクリックしたつもりが、<br>実際には透明なiframe内の『送金実行』をクリックしている"]X-Frame-Optionsの値
| 値 | 説明 |
|---|---|
DENY |
すべてのiframe埋め込みを禁止 |
SAMEORIGIN |
同一オリジンからの埋め込みのみ許可 |
X-Frame-Optionsの設定例
|
|
CSPのframe-ancestorsとの関係
CSPのframe-ancestorsディレクティブは、X-Frame-Optionsより柔軟な制御が可能です。CSPをサポートするブラウザではframe-ancestorsが優先されます。
|
|
両方のヘッダーを併用することで、古いブラウザと新しいブラウザの両方に対応できます。
|
|
X-Content-Type-Optionsの設定
X-Content-Type-Optionsは、ブラウザのMIMEタイプスニッフィングを無効にするセキュリティヘッダーです。
MIMEスニッフィング攻撃とは
ブラウザは、サーバーから送信されたContent-Typeヘッダーを無視して、コンテンツの内容からMIMEタイプを推測する機能(MIMEスニッフィング)を持っています。この機能が悪用されると、テキストファイルとしてアップロードされた悪意のあるスクリプトがHTMLやJavaScriptとして実行される可能性があります。
flowchart TD
A["1. 攻撃者がファイルをアップロード<br>ファイル名: image.jpg<br>内容: <script>alert('XSS')</script>"] --> B["2. サーバーはContent-Typeを返す<br>Content-Type: image/jpeg"]
B --> C["3. ブラウザがコンテンツをスニッフィング<br>『このファイルはHTMLっぽい...』"]
C --> D["HTMLとして解釈・実行"]
D --> E["XSS攻撃成功"]
style A fill:#ffcccc
style E fill:#ff6666X-Content-Type-Optionsの設定
設定は非常にシンプルです。
|
|
この設定により、ブラウザはContent-Typeヘッダーで指定されたMIMEタイプのみを信頼し、スニッフィングを行いません。
その他の重要なセキュリティヘッダー
Referrer-Policy
リファラー情報の送信を制御するヘッダーです。
|
|
| 値 | 説明 |
|---|---|
no-referrer |
リファラーを送信しない |
no-referrer-when-downgrade |
HTTPSからHTTPへのリクエスト時はリファラーを送信しない |
origin |
オリジンのみを送信 |
origin-when-cross-origin |
同一オリジンにはフルURL、クロスオリジンにはオリジンのみを送信 |
same-origin |
同一オリジンにのみリファラーを送信 |
strict-origin |
HTTPS→HTTPでは送信しない、それ以外はオリジンのみを送信 |
strict-origin-when-cross-origin |
推奨設定。HTTPS→HTTPでは送信しない、クロスオリジンにはオリジンのみを送信 |
unsafe-url |
常にフルURLを送信(非推奨) |
Permissions-Policy
ブラウザのAPI機能へのアクセスを制御するヘッダーです。
|
|
この設定では、位置情報、カメラ、マイクへのアクセスをすべて無効にしています。
X-DNS-Prefetch-Control
DNSプリフェッチを制御するヘッダーです。
|
|
外部ドメインへの不必要なDNSクエリを防ぎ、プライバシーを保護します。
主要フレームワークでのセキュリティヘッダー実装例
Nginx
Nginxの設定ファイル(nginx.confまたは個別のサーバー設定)にヘッダーを追加します。
|
|
alwaysパラメータを付けることで、エラーレスポンス時にもヘッダーが送信されます。
Apache
Apacheでは.htaccessファイルまたは仮想ホスト設定でヘッダーを追加します。
|
|
mod_headersモジュールが有効になっている必要があります。
Express.js(Node.js)
Express.jsでは、helmetミドルウェアを使用してセキュリティヘッダーを簡単に設定できます。
|
|
helmetをインストールするには以下のコマンドを実行します。
|
|
Spring Boot(Java)
Spring Bootでは、Spring Securityを使用してセキュリティヘッダーを設定できます。
|
|
セキュリティヘッダーの検証方法
設定したセキュリティヘッダーが正しく動作しているか検証することが重要です。
ブラウザの開発者ツールで確認
ChromeやFirefoxの開発者ツール(F12)でネットワークタブを開き、レスポンスヘッダーを確認できます。
curlコマンドで確認
|
|
レスポンスヘッダーが表示されます。
オンラインツールで確認
- Mozilla Observatory:総合的なセキュリティヘッダーの評価
- Security Headers:セキュリティヘッダーの詳細な分析
- CSP Evaluator:CSP設定の評価
まとめ
セキュリティヘッダーは、Webアプリケーションのセキュリティを強化するための重要な防御層です。
最低限設定すべきヘッダー
- Content-Security-Policy:XSS攻撃対策
- Strict-Transport-Security:HTTPS通信の強制
- X-Frame-Options:クリックジャッキング対策
- X-Content-Type-Options:MIMEスニッフィング対策
導入時の注意点
- CSPはReport-Onlyモードでテストしてから本番適用する
- HSTSは短いmax-ageから始めて段階的に延長する
- 既存機能への影響を十分にテストする
- 定期的にセキュリティヘッダーの設定を見直す
これらのセキュリティヘッダーを適切に設定することで、Webアプリケーションの防御力を大幅に向上させることができます。
参考リンク
- MDN Web Docs - Content-Security-Policy
- MDN Web Docs - Strict-Transport-Security
- OWASP HTTP Headers Cheat Sheet
- OWASP Content Security Policy Cheat Sheet
- OWASP HTTP Strict Transport Security Cheat Sheet
- HSTS Preload List Submission
- Mozilla Observatory
- CSP Evaluator by Google
- helmet - npm
- Spring Security Reference - Headers