HTTP Strict Transport Security(HSTS)とは?
はじめに
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 ) 設定が行われています。
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年間を表しています。
ブラウザはその指示を受けて、自分の中にあるリスト内 (キャッシュ) にドメイン名「example.com」を登録しておきます。
自分のブラウザが登録しているキャッシュ情報の確認・削除等は、Chromeの場合はchrome://net-internals/#hsts で行うことができます。
ユーザーが再び「example.com」にhttp
でアクセスしてきたときは、ブラウザはWebサーバに問い合わせを送る前に、まず自分のキャッシュに「example.com」が存在するかどうかをチェックし、あればhttp
をhttps
に変換してリクエストを送信します。
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などの他の主要なブラウザでもこのリストを読みにきます。
『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
こんにちは。図でHTTPリクエストでHSTSヘッダを載せていますが、MDNの解説にあるように、HTTPリクエストではブラウザはHSTSを無視します。
なので、図のようなことをやりたければ、いったんHTTPSに301リダイレクトしてからHTTPSのレスポンスでHSTSを設定することになります。