初期リクエストの問題点
HTTPS は接続確立後のトラフィックを暗号化しますが、HTTP で行われる最初のリクエストは平文のまま送信されます。同じネットワーク上の攻撃者はこの最初のリクエストを傍受し、SSL ストリッピング攻撃 によってセッション全体を HTTP にダウングレードできます。
HTTP Strict Transport Security(HSTS)はこの問題を解決します。ブラウザが HSTS ヘッダーを受け取ると、以後すべての HTTP リクエストを 自動的に HTTPS にアップグレード し、証明書が無効な場合は接続を拒否します。
HSTS の仕組み
サーバーは HTTPS レスポンスで Strict-Transport-Security ヘッダーを送信します:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
| ディレクティブ | 説明 |
|---|---|
max-age=<秒> | HTTPS のみを使用するようブラウザが記憶する期間 |
includeSubDomains | すべてのサブドメインにポリシーを適用 |
preload | ブラウザのプリロードリストへの登録を希望 |
ブラウザはこのヘッダーを受け取ると:
- ドメインの
http://リンクをすべてhttps://に書き換え - TLS ハンドシェイクが失敗したり証明書が無効な場合は接続を拒否
max-ageで指定された期間ポリシーをキャッシュ
サーバーでの設定
NGINX
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/example.pem;
ssl_certificate_key /etc/ssl/private/example.key;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
}
always パラメータにより、エラーページでもヘッダーが送信されます。
Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Cloudflare
Cloudflare のダッシュボードから HSTS を有効化できます:SSL/TLS > Edge Certificates > HTTP Strict Transport Security。プリロードや includeSubDomains の切り替えはワンクリックです。
Express/Node.js
const helmet = require("helmet");
app.use(helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true
}));
HSTS プリロードリスト
max-age はユーザーが少なくとも一度サイトに訪問した後にのみ機能します。ブラウザに組み込まれた HSTS プリロードリスト(Chrome、Firefox、Safari、Edge)は、常に HTTPS を使用すべきドメインをハードコードし、初期リクエストの脆弱性を根本的に排除します。
登録手順:
- サイトが
preloadを含む有効な HSTS ヘッダーを返すことを確認 - hstspreload.org にアクセス
- ドメインを送信
プリロード登録の要件:
| 要件 | 詳細 |
|---|---|
| 有効な証明書 | すべてのサブドメインで TLS 対応 |
max-age | 最低 31536000(1年) |
includeSubDomains | 必須 |
preload | ヘッダーに含める |
| リダイレクト | すべての HTTP → HTTPS リダイレクト |
警告: プリロード登録は実質的に永続的です。一度受理されると、ドメインをリストから簡単に削除できません。
HSTS 設定のテスト
いくつかのツールで設定を検証できます:
# curl でヘッダー確認
curl -sI https://example.com | findstr -i "strict-transport"
# Security Headers: https://securityheaders.com
# SSL Labs: https://www.ssllabs.com/ssltest/analyze.html?d=example.com
# HSTS プリロード状態の確認
curl -s https://hstspreload.org/api/v2/check?domain=example.com
よくある問題
| 問題 | 影響 | 解決策 |
|---|---|---|
max-age が短すぎる | ポリシーが頻繁に期限切れ | 最低1年に設定 |
includeSubDomains がない | サブドメインが保護されない | ディレクティブを追加 |
| HTTP のみのサイトで HSTS を配信 | ヘッダーが無視される | HTTPS でのみ配信 |
| 混合コンテンツ | ブラウザが安全でないリソースをブロック | すべての http:// 参照を監査 |
| 準備なしのプリロード | 恒久的な HTTPS 必須化 | まず max-age=0 でテスト |
開発時の HSTS 解除
キャッシュされた HSTS ポリシーをクリアする方法:
- Chrome:
chrome://net-internals/#hsts→ Delete domain - Firefox: ドメインの閲覧履歴を消去
- Safari: 環境設定から Web サイトデータを消去
開発時は max-age=0 でポリシーを取り消せます:
Strict-Transport-Security: max-age=0
まとめ
HSTS は、初回訪問以降の HTTPS 利用を強制し、SSL ストリッピングやダウングレード攻撃を防ぐ基本的なセキュリティヘッダーです。max-age=31536000、includeSubDomains、オプションで preload を設定して完全な保護を実現しましょう。セキュリティチェッカーで設定を検証し、開発中は HSTS キャッシュを適宜クリアしてください。

