HSTSが防ぐもの、防げないもの:max-age、includeSubDomains、preload

Strict-Transport-Security ヘッダーを受け取ったブラウザが何を変えるのかを RFC 6797 で整理します。初回アクセスの問題、includeSubDomains の利点と危険、段階的な max-age、いま preload が推奨されない理由まで。

開発セキュリティ

http:// で始まるリンクをクリックしても、平文のリクエストを送らずにアドレスを https:// に書き換えてしまうサイトがあります。そのサイトが以前送った Strict-Transport-Security レスポンスヘッダーをブラウザが覚えているからです。この動作を定めているのが RFC 6797 の HSTS(HTTP Strict Transport Security)です。

リダイレクトだけでは足りない理由

サーバーが 301 リダイレクトで HTTPS へ誘導していても、最初のリクエストは平文で出ていきます。hstspreload.org はこの時点で起きる攻撃を説明しています。経路上の攻撃者はリダイレクトを横取りして書き換え、ブラウザを HTTP のままにしておけますし、HTTP リクエストの Cookie を見たり改変したりでき、リダイレクトのレスポンスに Cookie を差し込むこともできます。HSTS のポリシーを持つブラウザは、その平文リクエストをそもそも送りません。

ブラウザがすること

Strict-Transport-Security: max-age=31536000; includeSubDomains

max-age は必須のディレクティブで、ヘッダーを受け取ってから何秒間そのホストを「既知の HSTS ホスト(Known HSTS Host)」として扱うかを決めます。includeSubDomains は任意で、ポリシーをすべてのサブドメインに広げます。RFC 6797 が定義するディレクティブはこの二つだけで、ブラウザは知らないディレクティブを無視し、残りを処理しなければなりません。

ブラウザがこのヘッダーを記録するのは、エラーのない安全な接続で受け取ったレスポンスからだけです。HTTP レスポンスに含まれるヘッダーは無視しなければならず(MUST)、サーバーも HTTP レスポンスにこのヘッダーを入れてはなりません(MUST NOT)。HTML の <meta http-equiv> で指定した値にも従わず、IP アドレスで接続したホストは記録しません。一つのレスポンスにヘッダーが複数あれば、最初の一つだけを処理します。

記録が有効な間、ブラウザはそのホストの http URI を読み込む前に、リダイレクトをたどる場合も含めて、スキームを https に置き換えます。明示されたポートが80なら443に変え、それ以外のポートはそのままにします。TLS 接続で証明書検証の失敗を含むエラーや警告が一つでもあれば、接続を切断しなければなりません(MUST)。RFC はこのとき利用者が警告をクリックして先へ進めないようにすることも勧めていますが、この部分は非規範の実装上の助言です。

後のレスポンスでヘッダーがなくなっても、ポリシーは max-age が尽きるまで残ります。消すには HTTPS で max-age=0 を送る必要があり、そのとき一緒に付いた includeSubDomains は無視されます。

初回アクセスは守れない

ブラウザがヘッダーを受け取るには、まず一度接続しなければなりません。まだポリシーのないホストに利用者が http のアドレスを入力したり、http のリンクをたどったりすると、最初のリクエストは平文で出ていきます。RFC 6797 はこれをブートストラップ MITM 脆弱性と呼んでいます。期限切れの記録は削除されるので、max-age が過ぎた後の最初の接続も同じ状況です。

RFC が緩和策として挙げるものの一つが、ブラウザにあらかじめ組み込んでおくプリロードリスト(pre-loaded list)です。Chrome は hstspreload.org を通じてこのリストを管理しており、Firefox、Safari、Edge などほかの主要ブラウザも Chrome のリストをもとにしたリストを持っています。

includeSubDomains の両面

RFC 6797 は、このディレクティブがないと Secure 属性付きのドメイン Cookie を守れないと説明しています。攻撃者が example.com の下に元々なかったサブドメインを DNS に登録して自分のサーバーに向け、ブラウザにそこへリクエストさせたとします。そのサブドメインには HSTS ポリシーがないため、利用者が証明書の警告をクリックして先へ進むと、Cookie が攻撃者に渡りえます。

逆に、HTTPS をきちんと提供していないサブドメインは、ポリシーを受け取ったブラウザから接続できなくなります。RFC の例は、CRL と OCSP を平文の HTTP で提供している認証局です。ca.example.com が includeSubDomains を送ると、そのブラウザは crl-and-ocsp.ca.example.com から証明書の状態を取得できなくなります。hstspreload.org も、外部に公開していない社内のサブドメインまで含めて、すべてが HTTPS で動くかを先に確かめるよう求めています。

ヘッダーをどこから送るかも考える必要があります。example.com だけがヘッダーを送り、利用者はいつも www.example.com から入ってくるなら、example.com に接続したことのないブラウザはポリシーを受け取れません。RFC は入口になるホストごとに直接ヘッダーを送るよう勧めています(非規範)。

max-age は段階的に上げる

hstspreload.org の導入の推奨は、すべての HTTPS レスポンスにヘッダーを付け、includeSubDomains を付けたまま max-age を 300(5分)、604800(1週間)、2592000(1か月)の順に上げるというものです。各段階で壊れたページやトラフィックなどの指標を確認し、その段階の max-age をすべて待ってから次に進みます。ヘッダーを受け取ったブラウザは max-age が尽きるか HTTPS で max-age=0 を受け取るまでポリシーを保持するので、短い値から始めれば、ミスをしたときに影響が続く期間も短くなります。RFC 6797 も、サーバーの設定システムでは max-age の既定値を0にして、運用者が意図せず HSTS を有効にしてしまうのを防ぐよう勧めています(非規範)。

preload はいま推奨されていない

hstspreload.org の申請要件は、有効な証明書、ポート80で待ち受けている場合は同じホストでの HTTP から HTTPS へのリダイレクト、すべてのサブドメインでの HTTPS、そしてベースドメインで max-age が 31536000 秒(1年)以上で includeSubDomains と preload を含むヘッダーです。preload は RFC 6797 が定義するディレクティブではなく、このリストへの登録を求める意思表示です。

2026年10月13日に確認した hstspreload.org は、HSTS は推奨するが HSTS preload は推奨しないと明記しています。Chrome や Safari をはじめ多くのブラウザが、ドメインの HSTS ポリシーとは関係なく HTTP のナビゲーションを自動で HTTPS にアップグレードするため、preload に価値があるのは能動的な攻撃者によってそのアップグレードが失敗する場合だけだ、という理由です。リストから外すのも簡単ではありません。削除が Chrome のアップデートで利用者に届くまで数か月かかり、ほかのブラウザについては保証できないとしています。そのため、HTTPS の設定ツールやガイドでは preload を既定で含めないよう求めています。

範囲

RFC 6797(2012年)は Standards Track の文書で、上で挙げた MUST と MUST NOT はその規範的な要件です。サーバー導入の助言(11節)とブラウザ実装の助言(12節)は、RFC 自身が非規範と明記している部分です。段階的な max-age、preload の申請要件、preload を推奨しない立場は、Chrome のプリロードリストの申請サイトである hstspreload.org の方針で、標準ではないため変わる可能性があります。

参考

ブログへ