こんにちは、AWSを使ったインフラ構築・運用を担当している大久保です。

今回は、HSTSについて調査・検証した内容と、ALBとEC2を使ったWebサイト環境での設定方法について話していきます。

追記


2024/11/22

AWSのアップデートにより、ALBでHSTSヘッダーを挿入出来るようになりました。

Application Load Balancer (ALB) now supports HTTP request and response header modification giving you greater controls to manage your application’s traffic and security posture without having to alter your application code.

This feature introduces three key capabilities: renaming specific load balancer generated headers, inserting specific response headers, and disabling server response header. With header rename, you can now rename all ALB generated Transport Layer Security (TLS) headers that the load balancer adds to requests, which includes the six mTLS headers and two TLS headers (version and cipher). This capability enables seamless integration with existing applications that expect headers in a specific format, thereby minimizing changes to your backends while using TLS features on the ALB. With header insertion, you can insert custom headers related to Cross-Origin Resource Sharing (CORS) and critical security headers like HTTP Strict-Transport-Security (HSTS). Finally, the capability to disable the ALB generated “Server” header in responses reduces exposure of server-specific information, adding an extra layer of protection to your application. These response header modification features give you the ability to centrally enforce your organizations security posture at the load balancer instead of enforcement at individual applications, which can be prone to errors.

AWS Application Load Balancer introduces header modification for enhanced traffic control and security(2024/11/22時点)

HSTSとは?


HSTSとはHTTP Strict Transport Securityの略で、クライアントとサーバー間の通信をHTTPSに強制する仕組みです。
サーバーがStrict-Transport-Securityヘッダーを送信し、受け取ったクライアント(ブラウザなど)側は以降の通信を必ずHTTPSで行うようになります。

上図のように、サーバー側からStrict-Transport-Securityヘッダーを1度受け取ったクライアントは、ユーザー側でhttp://を指定されてもhttps://に変換して通信を行ってくれます。
この時HTTPステータスコードは307 Internal Redirectとなり、サーバー側でのリダイレクトでなくクライアント側でリダイレクトしているような動きになります。

またRFCに「HTTP経由で送信されるStrict-Transport-Securityヘッダーは無効となる」というような記載があります。
実際に試してみたところ、HTTP通信時に渡されたStrict-Transport-Securityヘッダーは利用されず、それ以降の通信がHTTPSに強制されることはありませんでした。

An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.

7.2. HTTP Request Type(2024/10/28時点)

If an HTTP response is received over insecure transport, the UA MUST ignore any present STS header field(s).

8.1. Strict-Transport-Security Response Header Field Processing(2024/10/28時点)

HSTSプリロードとは?


サーバー側でStrict-Transport-Securityヘッダーを付与するだけだと、初回アクセス時はクライアント側でStrict-Transport-Securityヘッダーを持っていないので、HSTSが効かないという問題が発生します。

これを解決できるのがHSTSプリロードです。
HSTSプリロードとは、HSTSプリロードリスト(HSTSが有効になっているドメインリスト)をクライアント側で事前に読み込んでおき、初回アクセスからHSTS利用してHTTPS通信を強制することができる仕組みです。

HSTSプリロードリストにドメインを登録するには以下の条件を満たしている状態で、https://hstspreload.org/から申請を行う必要があります。

  1. 有効な証明書を利用している。
  2. ポート 80 でリッスンしている場合、 HTTP から HTTPS にリダイレクトさせている。
  3. すべてのサブドメインでHTTPS接続できる状態にしている。
  4. Strict-Transport-Securityヘッダーを設定している。
    • max-age31536000秒(1年)以上に設定している。
    • includeSubDomainsを設定している。
    • preloadを設定している。
    • HTTPS サイトから追加のリダイレクトを提供する場合、そのリダイレクトには HSTS ヘッダー (リダイレクト先のページではなく) が含まれている。

気になる方は、Submission RequirementsDeployment Recommendationsの内容を確認してみてください。

※HSTSプリロードリストはブラウザのソースコードにハードコードされて利用されるものらしく、申請してから実際に反映されるまでに時間がかかるみたいです。

ALB+EC2(apache)環境での設定方法


では、ALBとEC2を利用している環境でどうやって設定すればいいか?
そんなに難しくなく、以下のことをすれば設定できます。

  1. ALBで80ポートのリスナーを作成し、強制的にHTTPS:443にリダイレクトさせる。
  2. EC2のapacheの設定ファイルで、Strict-Transport-Securityヘッダーを付与する設定を追加する。

※ 今回はHSTSプリロードリストへの登録までは行なわないので、apacheの設定は最低限にしています。

ALBのリスナーの設定

まずALBのリスナーの設定です。

以下の設定で、HTTP:80のリスナーを作成します。

  • リスナーの設定
    • プロトコル
      • HTTP
    • ポート
      • 80
  • デフォルトアクション
    • アクションのルーティング
      • URLにリダイレクト
    • URLにリダイレクト
      • URL部分
    • プロトコル
      • HTTPS
    • ポート
      • 443
    • ステータスコード
      • 301 - 完全に移動されました

Apacheの設定

次にApacheの設定です。

今回はubuntuを利用しているので、/etc/apache2/apache2.confに以下の設定を追記します。

Header always set Strict-Transport-Security "max-age=31536000"
設定説明
Header always set常に指定したヘッダーをHTTPレスポンスに追加する。
Strict-Transport-Security追加するヘッダー名。
ヘッダー名をStrict-Transport-Securityに設定。
"max-age=31536000"追加するヘッダーのパラメーター。
HSTSの有効期間を365日に設定。

※apacheのメインファイルに設定を追加していますが、vhostごとに設定したい場合はそれぞれのvhostの<VirtualHost>ディレクティブ内に設定を追記してください。

ヘッダーを付与するためにApacheのheadersモジュールを有効化し、Apacheを再起動します。

sudo a2enmod headers
sudo systemctl restart apache2

HSTSの確認

ブラウザの開発者ツールを起動した状態でHSTSの設定を行ったサイトにアクセスし、レスポンスヘッダーにStrict-Transport-Securityヘッダーが付与されているか確認します。

次に、chrome://net-internals/#hstsにアクセスし、Query HSTS/PKP domainの検索欄にアクセスしたドメインを入力してQueryをクリックします。
結果がFoundになっていればOKです。

最後に、HSTSによって本当にHTTP通信がHTTPS通信に変わるか確認します。

ブラウザの開発者ツールを起動した状態でHSTSの設定を行ったサイトにhttp://でアクセスします。
レスポンスで、HTTPステータスコードが307 Internal Redirect、ヘッダーにnon-authoritative-reason: HSTSがあればHSTSによるリダイレクトが成功してます。

ALBとEC2間がHTTP通信だけどいいの?


ALBとEC2を使った構成の場合、Route53でドメインを取得・ACMで証明書を取得し、ALBをSSL終端にすることが多いと思います。
この場合、クライアントとALB間はHTTPS:443で通信しますが、ALBとEC2間はHTTP:80で通信することになります。

ALBとEC2間の通信がHTTP:80通信のため、冒頭で記載した「HTTP経由で送信されるStrict-Transport-Securityヘッダーは無効」という仕様に抵触し、Strict-Transport-Securityヘッダーがクライアントで利用されないのでは?と思いましたが、そうはなりませんでした。

結果からの予想ですが、「HTTP通信時は無視される」というのは「クライアントへのレスポンスがHTTP:80通信だった場合、クライアントはStrict-Transport-Securityヘッダーを無視する」ということだと思います。

まとめ


今回の調査で、HSTSの設定方法について記載しました。
HSTSを設定することで、完全ではないですがCookieのセッションハイジャックの対策を行うことが出来ます。

この情報が誰か助けになれば幸いです。

参考にしたもの


By okubo

主にAWS上でのインフラ構築を担当してます。 ・AWS Certified Solutions Architect - Professional ・AWS Certified DevOps Engineer - Professional ・AWS Certified Database - Specialty ・AWS Certified Security - Specialty