結論(HSTSが設定されている)
HSTSが設定されているとは、HTTPSの応答にStrict-Transport-Security(HSTS)ヘッダーが付き、1以上のmax-ageで有効なポリシーをブラウザに伝えている状態です。HSTSを受け取ったブラウザは、max-ageの期間中そのホストへの接続をすべてHTTPSに自動変換し、証明書エラー時に警告を無視して進むことも許しません。HTTPからHTTPSへの転送だけでは防げないSSL Strip攻撃を、2回目以降のアクセスで塞ぐ仕組みです。
この記事のポイント
- 書式は Strict-Transport-Security: max-age=31536000 のように書き、max-ageは必須です。
- HSTSはHTTPSで受け取った場合だけ有効で、HTTP応答に付けても無視されます。
- max-age=0は「ポリシーの削除」を意味し、設定していないのと同じ扱いになります。
- 1つの応答に複数のHSTSヘッダーがあると、ブラウザは最初の1つだけを処理します。
- max-age=300(5分)から始めて1週間→1か月→1年以上と段階的に延ばすのが安全です。
- セキュリティAIチェッカーは、HTTPS応答に1以上のmax-ageがあれば○、なければ×、HTTP応答なら対象外とします。
| 診断項目名 | HSTSが設定されている |
|---|---|
| 項目ID | transport.hsts |
| 分類 | 通信の暗号化(HTTPS・TLS・HSTS) |
| 重大度・配点の重み | 重要(high) 重み 4 |
| 関連する標準・ガイドライン | RFC 6797(HTTP Strict Transport Security)、OWASP ASVS 5.0.0 V3.4.1(L1:全応答にStrict-Transport-Securityを含め、max-ageは1年以上。L2以上はサブドメインにも適用)、OWASP WSTG-CONF-07(Test HTTP Strict Transport Security)、OWASP HTTP Strict Transport Security Cheat Sheet、CWE-319 |
HSTSが設定されているとは
HSTSが設定されているとは、HTTPSの応答に Strict-Transport-Security(HSTS)ヘッダーが付いており、ブラウザに有効なHSTSポリシーを伝えている状態のことです。HSTSを受け取ったブラウザは、指定された期間(max-age)、そのホストへの接続をすべてHTTPSに自動変換し、証明書エラーが起きても利用者が警告を無視して進むことを許しません。
HTTPからHTTPSへの転送だけでは、最初のHTTPリクエストを経路上で横取りされる弱点(SSL Strip攻撃)が残ります。HSTSは、2回目以降のアクセスでこの弱点を塞ぐ仕組みです。セキュリティAIチェッカーでは重大度high、重み4の項目です。
Strict-Transport-Securityヘッダーの書式(RFC 6797 §6.1)
Strict-Transport-Security: max-age=31536000; includeSubDomains
| ディレクティブ | 必須 | 意味 |
|---|---|---|
max-age | 必須 | ポリシーを記憶する秒数。値は引用符で囲んでもよい |
includeSubDomains | 任意 | サブドメインにも同じポリシーを適用する |
preload | 仕様外 | ブラウザのプリロードリスト登録の意思表示(hstspreload.orgの要件) |
- ディレクティブ名は大文字・小文字を区別しません。
max-age=0は「このホストをHSTSホストとして扱うのをやめる」という意味で、ポリシーの削除指示です(§6.1.1)。max-ageのないヘッダーは仕様上の要件を満たさず、ブラウザは無視します。
各ディレクティブの詳しい基準は、「HSTSの有効期間」、「HSTSをサブドメインにも適用」、「HSTS Preload要件」の各項目で解説しています。
HSTSはどのように働くのか(仕組みと限界)
ブラウザの処理規則(RFC 6797 §8.1)
- HTTPSで受け取った場合だけ有効:HTTP(平文)の応答に付いたHSTSヘッダーは無視されます。攻撃者がHTTP応答にヘッダーを挿入・削除できてしまうためです(MDNも同様に説明しています)。
- 複数あれば最初の1つだけ:1つの応答に複数のHSTSヘッダーがある場合、ブラウザは最初のものだけを処理します。CMSとWebサーバーの双方で付与して重複させると、意図しない方が使われることがあります。
- IPアドレスには適用されない:IPアドレスで接続した場合、HSTSホストとして記録されません(§8.1.1)。
HSTSの効果と限界
- 効果:HSTSが記録されたホストについて、ブラウザは
http://のリンクやアドレス入力を、通信前にhttps://へ置き換えます。証明書エラー時は「無視して進む」が提供されません(§12.1)。 - 限界(初回訪問):HSTSは、少なくとも一度HTTPSで接続してヘッダーを受け取るまで効きません。初回の平文リクエストは攻撃を受けうるため、これを補うのがプリロードです(MDN)。
HSTSについてよくある誤解
- 「HTTPの応答にもHSTSを付ければ、HTTPでも強制できる」:HTTP応答のHSTSは無視されます。HTTP側では転送だけを行い、HSTSはHTTPS応答に付けます(転送は「HTTPからHTTPSへ転送」で確認します)。
- 「max-age=0でも書いてあれば設定済み」:0はポリシーの削除です。設定していないのと同じか、それ以上に誤解を招きます。
- 「トップページだけ付ければよい」:ASVS V3.4.1は「すべての応答」に含めることを求めています。どのページから訪れてもポリシーが記録されるよう、サーバー全体で付与します(複数ページ診断の「HSTSを全HTTPS応答へ適用」で確認します)。
HSTSが設定されているの診断基準(セキュリティAIチェッカー)
取得方法
- 入力URLへGETリクエストを送り、リダイレクトをたどった最終応答のレスポンスヘッダーを確認します。
- 最終URLが
https:の場合だけ評価します(HTTPで受け取ったHSTSはブラウザが無視するため)。 - 同じ名前のヘッダーが複数あるとカンマで連結されるため、先頭の1つ(ブラウザが処理するもの)を評価対象とします。
max-ageはmax-age=31536000とmax-age="31536000"のどちらの書式も解釈します。
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| ○ 問題なし(pass) | 最終URLが https: で、HSTSヘッダーに1以上の整数の max-age がある | 重み4を加算 |
| × 要改善(fail) | 最終URLが https: で、HSTSヘッダーがない | 0点 |
| × 要改善(fail) | HSTSヘッダーはあるが max-age がない、数値でない、または max-age=0(ポリシーとして機能しない) | 0点。根拠欄にヘッダーの値と理由を表示 |
| 対象外(na) | 最終URLが http:(HTTPS応答ではない) | 採点から除外 |
- この項目が○になると、関連項目「HSTSの有効期間」「HSTSをサブドメインにも適用」「HSTS Preload要件」が評価されます。この項目が×または対象外の場合、それらは対象外になります。
- HTTPのみのサイトは対象外ですが、「HTTPSで配信されている」(
transport.https、重み5)が×になります。
自治体サイトでの判定例
| 最終応答のヘッダー | 判定 |
|---|---|
Strict-Transport-Security: max-age=31536000; includeSubDomains | ○ |
Strict-Transport-Security: max-age=300 | ○(「HSTSの有効期間」は△) |
| ヘッダーなし | × |
Strict-Transport-Security: max-age=0 | ×(ポリシー削除の指示) |
Strict-Transport-Security: includeSubDomains(max-ageなし) | ×(無効なヘッダー) |
| HTTPのまま応答し、HSTSヘッダー付き | 対象外(HTTP応答のHSTSは無効) |
HSTSが設定されていないとどんなリスクがあるか
- SSL Strip攻撃:公衆無線LANなどで攻撃者がHTTP通信を中継し、HTTPSへの転送を止めて平文のまま偽ページを表示します。HSTSが記録されていれば、ブラウザは最初からHTTPSで接続するため成立しません。
- 証明書警告を無視させる攻撃:攻撃者が偽の証明書で中間者攻撃を仕掛けた際、HSTSがなければ利用者は警告を無視して進めてしまいます。HSTSがあれば進めません(OWASP Cheat Sheet)。
- HTTPリンクからの漏えい:サイト内や外部サイトに残る
http://リンクから遷移したときも、HSTSが記録されていれば平文の通信は発生しません。 - 導入時の副作用:HSTSは、記録されると期間中は取り消しにくい設定です。HTTPSに対応していないページが残った状態で長いmax-ageを設定すると、そのページは閲覧できなくなります。
HSTSの設定方法(Apache・nginx・IIS・Next.js)
段階的な導入手順
hstspreload.orgは、短いmax-ageから始めて段階的に延ばす方法を勧めています。OWASP Cheat Sheetも、初期導入時の設定ミスに備えた短いmax-age(86400秒)の例を示しています。
- HTTPからHTTPSへの転送と、主要ページのHTTPS表示を確認する。
max-age=300(5分)で導入し、問題がないか確認する。max-age=604800(1週間)→max-age=2592000(1か月)と延ばす。各段階で、前の段階のmax-ageの期間以上待ってから次に進む。- 最終的に
max-age=31536000(1年)以上にする(ASVS V3.4.1)。
Apache(.htaccess またはVirtualHost)
<IfModule mod_headers.c>
# HTTPS応答だけに付与。always でエラー応答や転送応答にも付ける
Header always set Strict-Transport-Security "max-age=31536000" env=HTTPS
</IfModule>
env=HTTPS はmod_sslが設定する環境変数を条件にしています。CDNやロードバランサーでTLSを終端している構成では、この条件が成立しないため、CDN側で付与します。
nginx
server {
listen 443 ssl;
# always でエラー応答にも付与
add_header Strict-Transport-Security "max-age=31536000" always;
}
nginxの add_header は、下位の location ブロックで別の add_header を書くと、上位の設定が継承されません。location ごとに付け直すか、共通ファイルを include してください(nginx 1.29.3以降は add_header_inherit merge; で上位の設定を引き継げます)。
IIS(10.0 version 1709以降)
<site name="CityWeb">
<hsts enabled="true" max-age="31536000" redirectHttpToHttps="true" />
</site>
Next.js(Vercel)
Vercelは独自ドメインに Strict-Transport-Security: max-age=63072000; を既定で付与します。値を変える場合は next.config.js のheadersで設定します。
// next.config.js
module.exports = {
async headers() {
return [{
source: "/:path*",
headers: [{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains" }],
}];
},
};
HSTSの確認方法
curl -sI https://www.city.example.lg.jp/ | grep -i '^strict-transport-security'
# 重複していないか(2行以上出たら重複)
curl -sI https://www.city.example.lg.jp/ | grep -ic '^strict-transport-security'
# 存在しないページ(404)にも付いているか
curl -sI https://www.city.example.lg.jp/not-found-check | grep -i '^strict-transport-security'
サイトを壊さないための注意点
- HSTSを付ける前に、そのホストのすべてのページ・ファイル・管理画面がHTTPSで表示できることを確認します。
- HSTSの設定は、Webサーバー・CMS・CDNのいずれか1か所に統一します。複数か所で付与すると重複し、ブラウザは最初のものだけを使います。
- 撤回が必要になった場合は、
max-age=0をHTTPSで返すと、次にアクセスしたブラウザから記録が消えます。訪問しないブラウザには長いmax-ageの記録が残るため、本格運用前の短いmax-ageでの試験が重要です。 - 共有ホスティングで
.htaccessを編集する際は、変更前のファイルを保存し、IfModuleで囲んでモジュール未導入時の500エラーを防ぎます。
よくある質問(FAQ)
HSTSとは何ですか?
HSTS(HTTP Strict Transport Security)は、HTTPS応答のStrict-Transport-Securityヘッダーで「このホストにはHTTPSでのみ接続する」ことをブラウザに記憶させる仕組みです(RFC 6797)。記録の期間中、ブラウザは http:// のリンクやアドレス入力を通信前に https:// へ置き換えます。
HTTPの応答にHSTSヘッダーを付ければ、HTTPでも強制できますか?
できません。HTTP(平文)の応答に付いたHSTSヘッダーは、攻撃者が挿入・削除できるためブラウザに無視されます。HTTP側では転送だけを行い、HSTSはHTTPS応答に付けます。
HTTPSへの転送を設定していればHSTSは不要ですか?
必要です。転送は最初のHTTPリクエストが平文で送られた後に行われるため、経路上で横取りされるとHTTPSへ移れません(SSL Strip攻撃)。HSTSが記録されていれば、ブラウザは最初からHTTPSで接続します。
max-age=0と書いてあればHSTSは設定済みですか?
設定済みではありません。max-age=0は「HSTSホストとして扱うのをやめる」というポリシー削除の指示です。セキュリティAIチェッカーでも、max-ageがない・数値でない・0の場合は×と判定します。
HSTSはトップページだけに付ければよいですか?
ASVS V3.4.1は「すべての応答」に含めることを求めています。どのページから訪れてもポリシーが記録されるよう、サーバー全体で付与してください。全ページへの付与は「HSTSを全HTTPS応答へ適用」の項目で確認します。
HSTSの設定を取り消したいときはどうすればよいですか?
ヘッダーを削除するのではなく、HTTPSでmax-age=0を返します。次にアクセスしたブラウザから記録が消えますが、訪問しないブラウザには記録が残るため、本格運用の前に短いmax-ageで試験することが重要です。
VercelではHSTSの設定が必要ですか?
Vercelは独自ドメインに Strict-Transport-Security: max-age=63072000; を既定で付与します。includeSubDomainsを付けるなど値を変える場合は、next.config.js のheadersで設定します。
この項目を含む127項目を、URLを入れるだけで無料診断します。
参考資料
- RFC 6797 HTTP Strict Transport Security
- OWASP ASVS 5.0.0 V3 Web Frontend Security
- OWASP WSTG-CONF-07 Test HTTP Strict Transport Security
- OWASP HTTP Strict Transport Security Cheat Sheet
- MDN Strict-Transport-Security
- HSTS Preload List Submission(hstspreload.org)
- Microsoft Learn「HSTS Settings for a Web Site <hsts>」
- Vercel Docs「Encryption and TLS」