• 診断項目 No.5/127
  • 通信の暗号化(HTTPS・TLS・HSTS)
  • 重大度 重要(high)

HSTSが設定されているとは?Strict-Transport-Securityの仕組み・設定方法・診断基準

HSTSが設定されているとは、HTTPS応答に有効なmax-ageを持つStrict-Transport-Securityヘッダーがある状態です。SSL Strip攻撃を防ぐ仕組み、HTTP応答では無効な理由、段階的な導入手順と各サーバーの設定例を解説します。

結論(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が設定されている
項目IDtransport.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秒)の例を示しています。

  1. HTTPからHTTPSへの転送と、主要ページのHTTPS表示を確認する。
  2. max-age=300(5分)で導入し、問題がないか確認する。
  3. max-age=604800(1週間)→ max-age=2592000(1か月)と延ばす。各段階で、前の段階のmax-ageの期間以上待ってから次に進む。
  4. 最終的に 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で設定します。

セキュリティAIチェッカーを利用する

この項目を含む127項目を、URLを入れるだけで無料診断します。

参考資料