• 診断項目 No.117/127
  • セキュリティヘッダー
  • 重大度 重要(high)

HSTSを全HTTPS応答へ適用とは?全ページ付与が必要な理由・設定方法・診断基準

HSTSを全HTTPS応答へ適用とは、トップページだけでなく下層ページ・API・エラー応答にもStrict-Transport-Securityを付けることです。全応答が必要な理由、Apache・nginx・IIS・Next.jsの共通設定、確認方法、診断基準を解説します。

結論(HSTSを全HTTPS応答へ適用)

HSTSを全HTTPS応答へ適用とは、Strict-Transport-Securityヘッダーを、トップページだけでなく下層ページ・API・404などのエラー応答を含むすべてのHTTPS応答に付けることです。OWASP ASVS 5.0.0 V3.4.1が「すべての応答」への付与を求めています。検索から下層ページへ直接来た利用者にも最初のHTTPS応答でHSTSを登録させるため、Webサーバーの共通設定で一括付与するのが確実です。

この記事のポイント

  • HSTSは1つのHTTPS応答で受け取ればホスト全体に効きますが、最初に訪れるページがトップとは限らないため全応答への付与が必要です。
  • 一部のページだけ付いていない状態は、設定の場所が分散していることを示し、構成変更時に保護が外れる原因になります。
  • セキュリティAIチェッカーはトップと下層最大2ページのHTTPS応答を調べ、1つでも有効なHSTS(max-age 1以上)がなければ×と判定します。
  • Apacheはalways付きのHeader設定、nginxはalways付きadd_headerで、エラー応答にも付与されます。
  • nginxではlocation内にadd_headerが1つでもあると上位の設定が継承されず、下層ページだけHSTSが消える典型原因になります。
診断項目名HSTSを全HTTPS応答へ適用
項目IDcrawl.hsts-coverage
分類セキュリティヘッダー
重大度・配点の重み重要(high) 重み 4
関連する標準・ガイドラインOWASP ASVS 5.0.0 V3.4.1(すべての応答に Strict-Transport-Security を含め、max-age は1年以上。L2以上はサブドメインにも適用、L1)、RFC 6797(HTTP Strict Transport Security)、OWASP WSTG-CONF-07(HTTP Strict Transport Security)、CWE-319(Cleartext Transmission of Sensitive Information)

HSTSを全HTTPS応答へ適用とは

HSTSを全HTTPS応答へ適用とは、Strict-Transport-Security(HSTS)レスポンスヘッダーを、トップページだけでなく、下層ページ・API・404などのエラー応答を含むすべてのHTTPS応答に付けることです。

HSTS(HTTP Strict Transport Security)は、「このホストには今後一定期間HTTPSだけで接続せよ」とブラウザに記憶させる仕組みです。トップページだけにHSTSを付けても、下層ページ・API・エラー応答で付け忘れがあると、設定の仕組みが一貫していないことを示し、構成変更時に保護が外れる原因になります。OWASP ASVS 5.0.0 V3.4.1 は「すべての応答」にHSTSを含めることを求めています。

セキュリティAIチェッカーのこの項目は、トップページと巡回した下層ページのHTTPS応答のそれぞれに、有効なHSTSヘッダーがあるかを確認します。HSTSの有無そのものは「HSTSが設定されている」、期間の長さは「HSTSの有効期間」、サブドメインへの適用は「HSTSをサブドメインにも適用」、プリロード登録は「HSTS Preload要件」で評価します。このページは「全ページ・全応答に漏れなく付いているか」という適用範囲に絞って解説します。

ブラウザはHSTSをどう処理するか(RFC 6797)

  • ブラウザは、HTTPSで受け取った有効な Strict-Transport-Security ヘッダーだけを処理します。HTTPで受け取ったヘッダーは無視されます(RFC 6797 8.1)。サーバー側もHTTP応答にはこのヘッダーを含めてはならないとされています(7.2)。
  • max-age は秒数で、ブラウザがHSTSホストとして記憶する期間です。max-age=0 はHSTS登録の削除を意味します(6.1.1の注記)。
  • includeSubDomains を付けると、すべてのサブドメインにも適用されます。
  • 同じ応答に複数の Strict-Transport-Security ヘッダーがある場合、ブラウザは最初の1つだけを処理します(8.1)。
  • 記憶期間中は、利用者が http:// のURLを入力しても、ブラウザ内部でHTTPSに書き換えてから接続します。証明書エラー時に「無視して進む」こともできなくなります。

なぜHSTSは「全応答」に必要なのか

HSTSは、ブラウザがどれか1つのHTTPS応答で受け取れば、そのホスト全体に効きます。そのため、全ページで付いていなくても理論上は保護が成立します。それでもASVSが全応答を求めるのは、次の理由からです。

  • 最初に訪れるページはトップとは限らない:検索結果から下層ページへ直接来た利用者にも、最初のHTTPS応答でHSTSを登録させるためです。
  • 記憶は失効・消去される:ブラウザの記憶は max-age で失効し、利用者がデータを消去することもあります。どのページを訪れても再登録されるようにするためです。
  • 付け忘れは設定の分散を示す:一部のページだけ付いていない状態は、アプリケーション側で個別にヘッダーを付けているなど、設定の場所が分散していることを示します。サーバー共通設定で付ければ漏れは起きません。

HSTSについてよくある誤解

  • 「HTTP→HTTPSリダイレクトがあればHSTSは不要」:リダイレクトの前に最初のHTTP通信が発生し、そこが中間者攻撃で書き換えられます。HSTSはその最初の通信自体をなくします。
  • 「max-age=0 でも付いていれば良い」:これは登録の削除指示であり、保護になりません。
  • 「preload は付けるほど良い」:preload リストへの登録は全サブドメインのHTTPS化が前提で、取り消しにも時間がかかります。登録窓口の hstspreload.org 自身が、HSTSは推奨するが preload は推奨しない(主要ブラウザがHTTPSへの自動アップグレードを行うため利点が小さい)と案内しています。

HSTSを全HTTPS応答へ適用の診断基準(セキュリティAIチェッカー)

取得対象

  • トップページ(入力URLのリダイレクトをたどった最終応答)。
  • 巡回で発見した同一オリジンの下層ページのうち最大2ページ(ログイン・管理・アカウント系URLを優先)。下層ページはGETで取得し、リダイレクトは最大2回までたどり、応答上限180KB、タイムアウト5秒です。取得に失敗したページは評価対象から外れます。
  • 最終URLが https: の応答だけを評価対象とします。

有効なHSTSの条件

Strict-Transport-Security ヘッダーの最初の値(複数ヘッダーがある場合は先頭)に max-age= があり、その値が1以上であることを「有効」とします。max-age の長さ(1年以上か)や includeSubDomains の有無は、単一ページの HSTS 項目で評価します。本項目は「全応答に有効なHSTSが付いているか」という適用範囲だけを見ます。

判定条件

判定条件得点係数
○ 問題なし(pass)評価したすべてのHTTPS応答に有効なHSTSがある1
× 要改善(fail)HTTPS応答のうち1つでも、HSTSがない、max-age がない、または max-age=00
対象外(na)評価対象にHTTPSの応答が1つもない(HTTPのみのサイト等)計算から除外

重み4の高い項目で、× の場合は4点分すべてを失います。根拠欄には「何ページ中何ページで不足か」を表示します。

自治体サイトでの判定例

構成判定
Apache の .htaccess 先頭で Header always set Strict-Transport-Security "max-age=31536000" を設定し、トップも下層も付与される○
トップページ(静的HTML)にはWebサーバーで付与しているが、/cgi-bin/ の検索システムや別アプリの下層ページには付いていない×
CMSのPHPコードで header() を使ってトップページだけに付けている×
移行作業中に max-age=0 を設定したまま戻していない×

HSTSが一部のページに付いていないとどんなリスクがあるか

  • SSLストリップ攻撃:2009年に Moxie Marlinspike が公開した sslstrip に代表される攻撃で、公衆無線LANなどの中間者が、最初のHTTP通信やHTTPSへのリンクをHTTPに書き換え、利用者とサイトの通信を平文のまま中継します。利用者はHTTPSでない画面にログイン情報や申請内容を入力してしまいます。
  • Cookie の盗用:Secure 属性のないCookieは、HTTPで接続した瞬間に平文で送信されます。HSTSが登録されていればHTTP接続自体が起きません。
  • 証明書警告の無視:HSTSがない場合、偽の証明書による警告を利用者が「続行」で突破できます。HSTSホストでは続行できなくなります。
  • 下層ページだけ未登録の利用者:検索から下層の電子申請ページへ直接来た利用者が、その応答にHSTSがないと登録されず、次回のHTTP接続で攻撃を受ける余地が残ります。

HSTSを全HTTPS応答へ適用する設定方法(Apache・nginx・IIS・Next.js)

段階的な導入

  1. 全ページ・全サブドメインがHTTPSで正常に表示できることを確認する(混在コンテンツ、HTTPのみで動く古いシステムがないか)。
  2. 短い max-age(例:300秒、次に86400秒)で全応答に付与し、問題がないか数日〜数週間観察する。
  3. max-age=31536000(1年)へ延長する。ASVS V3.4.1 は1年以上を求めています。
  4. サブドメインもすべてHTTPS化できたら includeSubDomains を追加する。
  5. preload は必須ではありません。申請する場合は、hstspreload.org の要件(有効な証明書、同一ホストでのHTTP→HTTPSリダイレクト、全サブドメインのHTTPS対応、ヘッダーに max-age 31536000以上・includeSubDomains・preload)を満たし、取り消しが難しいことを理解したうえで別途判断する。

Apache(.htaccess または VirtualHost)

<IfModule mod_headers.c>
  # always を付けると、404・500などのエラー応答やリダイレクト応答にも付与される
  Header always set Strict-Transport-Security "max-age=31536000" env=HTTPS
</IfModule>

env=HTTPS はHTTPS接続のときだけ付けるための条件です。リバースプロキシ配下で HTTPS 環境変数が設定されない構成では、HTTPSの VirtualHost(<VirtualHost *:443>)内に書きます。

nginx

server {
    listen 443 ssl;
    add_header Strict-Transport-Security "max-age=31536000" always;
    # location 内で add_header を1つでも書くと、server の add_header は継承されない
}

nginx では、下位の location に add_header があると上位の設定が継承されません。下層ページだけHSTSが消える典型原因です。共通ヘッダーを include ファイルにまとめ、各 location でも読み込みます。nginx 1.29.3 以降は add_header_inherit merge; を指定すると、下位で定義した add_header に上位の値を追加する形で継承できます。

IIS

IIS 10.0 バージョン1709以降はサイト単位のHSTS設定があります。それ以前は customHeaders で付与します(HTTPSバインディングだけのサイトで使用)。

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Strict-Transport-Security" value="max-age=31536000" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Next.js(Vercel)

// next.config.js
module.exports = {
  async headers() {
    return [{
      source: "/:path*",
      headers: [{ key: "Strict-Transport-Security", value: "max-age=31536000" }],
    }];
  },
};

source: "/:path*" で全パスに適用します。APIルートや静的ファイルにも適用されることを確認してください。

全応答に付いているかの確認方法

for u in / /kurashi/ /shinsei/ /no-such-page; do
  printf "%s " "$u"
  curl -s -o /dev/null -D - "https://www.example.lg.jp$u" | grep -i '^strict-transport-security' || echo "(なし)"
done

存在しないURL(404応答)にも付いていれば、エラー応答を含めて付与できています。設定後はセキュリティAIチェッカーで再診断し、根拠欄で全ページに付いていることを確かめます。

サイトを壊さないための注意点(ガードレール)

  • HSTSを付けると、記憶期間中はHTTPで接続できなくなります。HTTPでしか動かないサブドメインや庁内向けシステムが同じドメイン配下にある場合、includeSubDomains を先に付けると利用できなくなります。
  • 証明書の更新切れはHSTS下では回避不能な障害になります。証明書の自動更新と期限監視を先に整えます。
  • 二重付与(WebサーバーとCMSの両方で付与)は、ブラウザが最初の値だけを使うため、値が異なると意図しない設定になります。付与箇所は1か所にします。

よくある質問(FAQ)

HSTSはトップページだけに付ければ十分ではありませんか?

ブラウザはどれか1つのHTTPS応答で受け取ればホスト全体に適用するため、理論上は保護が成立します。ただし利用者が最初に訪れるのはトップとは限らず、記憶はmax-ageで失効し利用者が消去することもあります。どのページからでも登録・再登録されるよう、ASVS 5.0.0 V3.4.1はすべての応答への付与を求めています。

404などのエラーページにもHSTSが必要ですか?

必要です。ASVSは「すべての応答」を求めています。Apacheでは「Header always set」、nginxでは「add_header ... always」とすると、エラー応答やリダイレクト応答にも付与されます。

nginxで下層ページだけHSTSが消えるのはなぜですか?

nginxでは、下位のlocationにadd_headerが1つでもあると、上位のadd_headerが継承されません。共通ヘッダーをincludeファイルにまとめて各locationで読み込むか、nginx 1.29.3以降ならadd_header_inherit merge;を使います。

HTTPからHTTPSへのリダイレクトがあればHSTSは不要ですか?

不要ではありません。リダイレクトの前に最初のHTTP通信が発生し、そこが中間者攻撃で書き換えられます。HSTSはその最初の通信自体をなくします。

max-age=0が付いているページはどう判定されますか?

max-age=0は登録の削除指示であり保護になりません。この項目ではHSTSがないのと同じ扱いになり、1ページでも該当すれば「× 要改善」です。

WebサーバーとCMSの両方でHSTSを付けても問題ありませんか?

同じ応答に複数のStrict-Transport-Securityがあると、ブラウザは最初の1つだけを処理します。値が異なると意図しない設定になるため、付与箇所は1か所にします。

HTTPのみのサイトはどう判定されますか?

評価対象にHTTPSの応答が1つもなければ対象外(na)です。HTTPS化そのものは別の項目で評価されます。

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

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

参考資料