自分を締め出さずにHSTSを設定する方法
Strict-Transport-Securityを段階的かつ元に戻せる形で展開し、1つの不正な証明書を障害に変えずにプライバシーを高めるための計画。
目次
- HSTSは、そうでなくなるまではシンプルです
- HSTSヘッダーが実際に行うこと
- 避けるべきロックアウトのシナリオ
- 1. 忘れられたサブドメインがHTTPSに対応していない
- 2. 証明書が期限切れになる
- 3. ステージングや内部ツールが本番ドメイン配下にある
- 4. preloadを通常のチェックボックスとして扱う
- 安全な展開計画
- Step 1: 管理しているすべてのホスト名を監査する
- Step 2: HSTSを追加する前にHTTPSを直す
- Step 3: 非常に短いmax-ageから始める
- Step 4: 段階的に増やす
- Step 5: includeSubDomainsは監査が本物になってから追加する
- Step 6: preloadは別プロジェクトとして扱う
- 設定例
- Nginx
- Apache
- CDNまたはエッジプラットフォーム
- HSTSを安全に取り消す方法
- リリース前のテストチェックリスト
- HSTSのプライバシー上の意味
HSTSは、そうでなくなるまではシンプルです
HTTP Strict Transport Security(通常はHSTSと略されます)は、ブラウザーに「このサイトでは常にHTTPSを使う」と伝えます。ブラウザーが有効なHTTPS接続を通じてこのヘッダーを受け取ると、指定された期間、そのルールを記憶します。
これは有用です。プロトコルダウングレード攻撃を防ぎ、意図しない安全でないリクエストを減らし、ユーザーがexample.comと入力したときにリダイレクト前の一瞬だけ平文HTTPに触れてしまう気まずい状況を避けられます。
同時に、これは粘着性があります。誤ったHSTSポリシーを公開すると、サーバーからヘッダーを削除した後も、ブラウザーが長くそのポリシーを適用し続けることがあります。チームが自分たちを締め出してしまうのはこのためです。正確には自分たちの管理画面からではなく、ユーザーのブラウザー、サブドメイン、ステージング環境、レガシーなエンドポイント、そして強制HTTPSにまだ対応していない忘れられたサービスから締め出されます。
目標はHSTSを避けることではありません。トグルのようにではなく、移行のようにデプロイすることです。
HSTSヘッダーが実際に行うこと
典型的なHSTSヘッダーは次のようなものです。
Strict-Transport-Security: max-age=31536000; includeSubDomains
重要な要素は3つあります。
max-age: ブラウザーがこのホストに対してHTTPSを強制する期間(秒)。includeSubDomains: そのルールをすべてのサブドメインにも適用するかどうか。preload: ドメインをブラウザーのpreloadリストに含めたいというシグナル。
ブラウザーは、有効なHTTPS経由で受け取った場合にだけ、このヘッダーを信頼します。証明書が無効、期限切れ、または不一致の場合、ブラウザーはそのレスポンスから新しいHSTSポリシーを受け入れるべきではありません。
ポリシーが保存されると、以後http://example.comへアクセスしようとした際、リクエストが送信される前にブラウザーがhttps://example.comへアップグレードします。ここにプライバシー上の利点があります。安全でないリクエストがデバイスの外に出ないのです。
避けるべきロックアウトのシナリオ
HSTSの失敗の多くは、メインのWebサイトが原因ではありません。エッジで起こります。
1. 忘れられたサブドメインがHTTPSに対応していない
includeSubDomainsは整理されて見えますが、その効き方は絶対的です。example.comに設定すると、次のようなものすべてに適用されます。
www.example.comapi.example.comold-crm.example.comprinter-setup.example.comstaging.example.com- そのドメイン配下のその他すべて
これらのホストのいずれかが有効なHTTPSを提供できない場合、HSTSポリシーをキャッシュしているユーザーはHTTP経由でそこへ到達できなくなります。
2. 証明書が期限切れになる
HSTSがない場合、ユーザーは証明書警告をクリックして先へ進むことがあります。これは望ましいセキュリティ慣行ではありませんが、現実には起こります。
HSTSがある場合、現代のブラウザーはそのホストに対する証明書エラーの簡単なバイパスを許しません。それこそが目的です。同時に、証明書更新は退屈なほど確実で、監視され、テストされている必要があるということでもあります。
3. ステージングや内部ツールが本番ドメイン配下にある
内部ツールを*.example.com配下に置くと、親ドメインがincludeSubDomainsを使い始めた時点で苦しくなることがあります。これらのツールが自己署名証明書、プライベート認証局、古いTLS設定、あるいはHTTPSなしで動いている場合、HSTSはその近道を露呈させます。
多くのチームが内部システムや実験的なシステムを、独自のセキュリティポリシーを持つ別ドメイン配下に置く理由のひとつです。
4. preloadを通常のチェックボックスとして扱う
HSTS preloadは単なる別のディレクティブではありません。ユーザーが一度もサイトを訪問する前から、ドメインをHTTPS専用としてブラウザーに同梱できるという意味です。
これは「初回訪問」の隙間を塞ぎますが、取り消すのははるかに困難です。preloadリストからの削除がユーザーに届くまでには、ブラウザーのリリースサイクルによって数週間から数か月かかることがあります。preloadは安定して成熟したドメインに適しています。サブドメインの棚卸しをまだ進めているサイトには適していません。
安全な展開計画
Step 1: 管理しているすべてのホスト名を監査する
includeSubDomainsを設定する前に、そのドメイン配下のすべてのホスト名を一覧化します。DNSレコードは出発点ですが、全体像ではありません。CDN設定、ホスティングのダッシュボード、メール関連のホスト名、古いマーケティングツール、ストレージバケット、内部ドキュメントも確認します。
各ホスト名について、次を確認します。
- HTTP、HTTPS、またはその両方を提供しているか。
- HTTPS証明書は有効で、自動更新されるか。
- HTTPからHTTPSへきれいにリダイレクトされるか。
- 公開されるべきものか。
- まだ必要なものか。
チームに本番環境のヘッダーデバッグ習慣がすでにあるなら、この作業はリダイレクトやヘッダーの確認と自然に並びます。このワークフローについては、本番環境でリダイレクトとHTTPヘッダーをデバッグするための小さなツールキットで取り上げました。
Step 2: HSTSを追加する前にHTTPSを直す
HSTSは壊れたHTTPS設定を安全にするものではありません。HTTPSを必須にするだけです。
有効化する前に、次を確認します。
- TLS証明書が正しいホスト名をカバーしている。
- 証明書が自動更新される。
- 可能な範囲で、HTTPが単一のきれいなホップでHTTPSへリダイレクトされる。
- 正規ホストへのリダイレクトが一貫している。たとえば非
wwwからwwwへ、またはその逆。 - アプリケーションのアセットが安全でない
http://URLに依存していない。
混在コンテンツは以前ほど一般的ではありませんが、古いCMSテーマ、分析スニペット、埋め込みメディア、ハードコードされた画像パスにはまだ現れます。
Step 3: 非常に短いmax-ageから始める
1年から始めてはいけません。5分から始めます。
Strict-Transport-Security: max-age=300
それを、テスト対象のホスト名だけにデプロイします。通常は正規の本番Webサイトです。この段階ではincludeSubDomainsを外しておきます。
その後、実際のブラウザーとコマンドラインリクエストでテストします。
curl -I https://example.com
Strict-Transport-Securityヘッダーが正確に1つだけ見えるべきです。アプリサーバーとCDNから重複したHSTSヘッダーが出ることは、混乱のよくある原因です。ブラウザーは一般に有効なポリシーを適用しますが、インシデントをデバッグしている人間に曖昧さは不要です。
Step 4: 段階的に増やす
何も壊れなければ、期間を段階的に増やします。
Strict-Transport-Security: max-age=86400
次に。
Strict-Transport-Security: max-age=604800
さらに必要なら。
Strict-Transport-Security: max-age=2592000
実用的なスケジュールは次のとおりです。
- 5分
- 1日
- 1週間
- 1か月
- 6か月または1年
急いでも賞はありません。段階的な展開の目的は、監視、サポート受信箱、そしてエッジケースが、チェックリストから漏れたものを教えてくれる時間を確保することです。
Step 5: includeSubDomainsは監査が本物になってから追加する
すべての公開サブドメインがHTTPS対応になったら、次を検討できます。
Strict-Transport-Security: max-age=31536000; includeSubDomains
ここは保守的になるべきタイミングです。1つでもレガシーサービスがまだHTTPを必要としているなら、親ドメインにincludeSubDomainsを追加してはいけません。そのサービスを移行するか、別ドメインへ移すか、あるいは当面はHSTSポリシーを狭いままにしておく必要があると受け入れます。
セキュリティヘッダーは現実を反映すべきです。将来そうしたいインフラに向けた啓発ポスターとして使うべきではありません。
Step 6: preloadは別プロジェクトとして扱う
preloadを検討するのは、次のすべてが真である場合だけです。
- ドメインとすべてのサブドメインが有効なHTTPSをサポートしている。
- HTTPがHTTPSへリダイレクトされる。
- HSTSヘッダーが少なくとも31536000秒の
max-ageを使用している。 - ヘッダーに
includeSubDomainsが含まれている。 - ヘッダーに
preloadが含まれている。 - そのドメイン配下のどこにも平文HTTPが不要だと確信している。
preload対応のヘッダーは次のようになります。
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
preloadリストへの送信は長期的なコミットメントです。サイトがキャンペーン用マイクロサイト、一時的なプロダクトドメイン、または所有境界が不明瞭なドメインであるなら、見送ってください。
設定例
Nginx
エラーレスポンスにもヘッダーが送信されるようにalwaysを使います。
add_header Strict-Transport-Security "max-age=300" always;
展開が安定した後は次のようにします。
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Apache
mod_headersが有効な場合。
Header always set Strict-Transport-Security "max-age=300"
後で次のようにします。
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
CDNまたはエッジプラットフォーム
CDNがレスポンスヘッダーを設定する場合、HSTSは1か所で管理するのが望ましいです。非常に明確な理由がない限り、オリジンで1つのポリシーを設定し、エッジで別のポリシーを設定しないでください。
また、CDNがリダイレクト、キャッシュされたエラー、カスタムエラーページにヘッダーを適用するかも確認します。本番サイトは200 OKレスポンスだけで成り立っているわけではありません。
HSTSを安全に取り消す方法
HSTSを無効にする必要がある場合は、次を送信します。
Strict-Transport-Security: max-age=0
ただし落とし穴があります。ブラウザーがそのヘッダーを受け取るには、有効なHTTPSでサイトへ正常に到達できなければなりません。HTTPS自体が壊れている場合、HSTSポリシーをキャッシュしているユーザーは、それをクリアする指示を取得できません。
そのため、通常の復旧順序は次のようになります。
- 有効なHTTPSを復旧する。
Strict-Transport-Security: max-age=0を配信する。- 再訪問ユーザーが受け取れるだけの期間、それを維持する。
- インシデント解決後にヘッダーを削除または置き換える。
ドメインがpreloadされている場合、max-age=0を配信するだけでは新しいブラウザープロファイルには不十分です。preloadリストからの削除も依頼し、その変更がブラウザー更新を通じて配信されるまで待つ必要があります。
リリース前のテストチェックリスト
max-ageを増やす前、またはincludeSubDomainsを追加する前に、このチェックリストを使います。
- 正規のHTTPS URLが有効な証明書を返す。
- HTTPがHTTPSへリダイレクトされる。
- HSTSヘッダーが1つだけである。
- 適切な箇所で、リダイレクトやエラーレスポンスにもヘッダーが表示される。
- すべての公開サブドメインに有効なHTTPSがある。
- 証明書更新が監視されている。
- 同じ親ドメイン配下で、重要な内部システムがHTTPに依存していない。
- preloadが習慣で追加されたのではなく、明示的に議論されている。
Lighthouseは状況によって、欠落しているセキュリティヘッダーや弱いセキュリティヘッダーを指摘することがありますが、唯一の検証方法にすべきではありません。より広いレビューの一部として使う場合は、結果を判定ではなくシグナルとして読みます。同じ考え方は、慌てずにLighthouseレポートを読むときにも当てはまります。
<!-- tool-cta:start -->
💡 これを試してください: HSTS を変更するたびに、その前後で Get Headers を使って Strict-Transport-Security response を確認し、max-age、includeSubDomains、preload が期待どおりであることを確かめてください。
<!-- tool-cta:end -->
HSTSのプライバシー上の意味
HSTSはしばしばセキュリティヘッダーとして語られますし、実際そうです。同時に、プライバシー上の利点もあります。信頼できないネットワーク上で、ユーザーの最初のリクエストが平文HTTPで漏れる可能性を減らします。
これは空港のWi-Fi、ホテルのネットワーク、企業のゲストネットワーク、そしてユーザーのトラフィックが観察または改変される可能性のあるあらゆる場所で重要です。平文HTTPリクエストは、ホスト名、パス、SecureフラグのないCookie、その他のリクエスト詳細をさらす可能性があります。HTTPSは魔法ではありませんが、一貫して強制することで、避けられる漏えいの一群を丸ごと取り除けます。
最良のHSTS展開は目立ちません。ゆっくり展開され、信頼できる証明書に支えられ、誰にも気づかれないほど退屈です。失敗時の影響が劇的になり得るヘッダーには、まさにそれが望ましい姿です。