🥑

HTTP Strict Transport Security(HSTS)とは?

2021/04/13に公開1

はじめに

Webサイトがどのように表示されるのかを知るために『What happens when...』を読みました。

しかし、HSTSが何なのか理解できず、かなり最初の方でつまづいてしまったので、今回の記事では自分が調べたことをまとめたいと思います。

「HSTSをチェックする」

以下が『What happens when...』で書かれていた説明です。

ブラウザは"preloaded HSTS(HTTP Strict Transport Security)"リストを調べます。これはHTTPSでのみリクエストを送るように求めているウェブサイトの一覧です。

もしそのウェブサイトがリストにあれば、ブラウザはHTTPではなくHTTPSでリクエストを送ります。なければ最初のリクエストはHTTPで送られます。ウェブサイトは、HSTS一覧になくてもHSTSポリシーを利用可能であることに注意してください。最初のHTTPリクエストに対するレスポンスは、HTTPSリクエストのみでリクエストを送ることを要求するものです。しかし、この1回のHTTPリクエストによりユーザはダウングレード攻撃を受ける可能性があります。そのため、現在のWebブラウザにはHSTS一覧が搭載されています。

なんのこっちゃという感じなので、調べてみます。

HSTSとは?

超簡単にいうと、ユーザーが「http://example.com/」にアクセスしようとしたとき、ブラウザが自動で「https://example.com/」に置き換えてアクセスしてくれる機能のことらしいです。

HSTSが設定されていなかったら?

一般的にSSL化したWebサイトでは、ユーザーがhttpでアクセスしてきても、httpsの方に強制的に遷移させるために、301リダイレクト( Moved Permanently ) 設定が行われています。

301.png

httpでリクエストしてきたユーザーに対して、Status Codeで301を返し、リダイレクト先のURLをLocationヘッダーに記すことで、httpsのアクセスの方に強制させているのです。

しかしこの場合、①と②で行われる通信は平文で暗号化もされない状態となっているため、悪い人に通信内容を盗聴・改ざんされる恐れがあります。

このような攻撃のことを「中間者攻撃」と呼びます。

HSTSは、この中間者攻撃から、httpでアクセスしてきたユーザーを守るための仕組みです。

HSTSが設定されていたら?

HSTSは、Webサーバ側が「strict-transport-security」というレスポンスヘッダーをブラウザに送信することで、httpsアクセスに強制させる仕組みです。

例えば、「example.com」にユーザーがhttpでアクセスしてきたとします。

Webサーバは、レスポンスヘッダーに「strict-transport-security: max-age=[ 秒数 ];」という項目を付加して、レスポンスを返します。

このstrict-transport-security ヘッダーというのは、ブラウザに「次回以降はHTTPの代わりにHTTPSを使うようにお願いね〜」というような指示を表しています。max-ageで秒数を指定することで、どれくらいの期間、指示を覚えさせておくかを指定します。下図の場合は 31536000 で、1年間を表しています。

hsts 2.png

ブラウザはその指示を受けて、自分の中にあるリスト内 (キャッシュ) にドメイン名「example.com」を登録しておきます。
自分のブラウザが登録しているキャッシュ情報の確認・削除等は、Chromeの場合はchrome://net-internals/#hsts で行うことができます。

ユーザーが再び「example.com」にhttpでアクセスしてきたときは、ブラウザはWebサーバに問い合わせを送る前に、まず自分のキャッシュに「example.com」が存在するかどうかをチェックし、あればhttphttpsに変換してリクエストを送信します。
Edgeなどの一部のブラウザでは、単にURLをhttpsに変更するだけみたいですが、Chromeなどのブラウザは307 Internal Redirectが行われます。

つまり、HSTSを設定している場合としてない場合では、次のような違いがあります。

  • HSTS設定なしの場合 ・・・ httpで通信 → httpsに301リダイレクト。毎回必ずhttp通信が発生する。
  • HSTS設定ありの場合 ・・・ 初回だけhttp通信をすれば、以降は有効期限内であれば、301リダイレクトなしにhttpsでの通信になる。

HSTSを設定することで、301リダイレクトよりも安全性は高まります。
しかし、上の説明にあるように初回はhttp通信を行うため、初回アクセス時は安全とは言えなさそうです。

この問題の解決方法として、preloaded HSTSというものがあります。

preloaded HSTSとは?

preloaded HSTSとは、このフォーム https://hstspreload.org/ に、あらかじめドメイン名を登録しておくことで、初回からhttpsの通信で行うようにブラウザに通知する仕組みのことです。

これに登録しておけば、初回アクセスを含め、常にhttpsでのアクセスを可能にします。

このフォームの管理はGoogleが行っているそうですが、Chrome以外でもFirefox、Safari、IE、Edgeなどの他の主要なブラウザでもこのリストを読みにきます。

スクリーンショット 2021-02-28 17.27.27.png

『What happens when...』では何を言っていたの?

preloaded HSTSについてざっくり理解したので、『What happens when...』に戻ります。

ブラウザは"preloaded HSTS(HTTP Strict Transport Security)"リストを調べます。これはHTTPSでのみリクエストを送るように求めているウェブサイトの一覧です。

もしそのウェブサイトがリストにあれば、ブラウザはHTTPではなくHTTPSでリクエストを送ります。なければ最初のリクエストはHTTPで送られます。ウェブサイトは、HSTS一覧になくてもHSTSポリシーを利用可能であることに注意してください。最初のHTTPリクエストに対するレスポンスは、HTTPSリクエストのみでリクエストを送ることを要求するものです。しかし、この1回のHTTPリクエストによりユーザはダウングレード攻撃を受ける可能性があります。そのため、現在のWebブラウザにはHSTS一覧が搭載されています。

この引用が何を言っているのかというと...

1.アドレスバーに入力されたURLが、http://~ だった。
2. ブラウザはまず、 https://hstspreload.org/ を見て、リクエスト先のドメイン名がこのリストに登録されているかどうかを確認する。
3. もしあれば、ブラウザはhttpsに置き換えてWebサーバにリクエストを送る。
4. なければ、なにも変更せずhttpのままでリクエストを送る。(ただし中間者攻撃のリスクは高まる。)
5. Webサーバは、レスポンスヘッダーに「strict-transport-security: max-age=[ 秒数 ];」を付加して、次回以降は必ずhttpsリクエストのみでリクエストを行うことを要求する。

以上のような流れになるんじゃないかなと思います。

参考

Discussion

ockeghemockeghem

こんにちは。図でHTTPリクエストでHSTSヘッダを載せていますが、MDNの解説にあるように、HTTPリクエストではブラウザはHSTSを無視します。

Note: メモ: サイトに HTTP を使用してアクセスしたとき、ブラウザーは Strict-Transport-Security ヘッダーを無視します。これは攻撃者が HTTP 接続に介入して、ヘッダーを挿入したり削除したりするかもしれないからです。ウェブサイトに HTTPS でアクセスして、証明書のエラーがない場合、ブラウザーはサイトが HTTPS でアクセスできることを知り、 Strict-Transport-Security ヘッダーを信用します。
Strict-Transport-Security - HTTP | MDN

なので、図のようなことをやりたければ、いったんHTTPSに301リダイレクトしてからHTTPSのレスポンスでHSTSを設定することになります。