トップレベルドメインの中に.devと.appがある.これらはHTTPS接続を強制するドメインとして知られている.この仕組みが気になっていたので調べてみた.
参考: グーグル、完全HTTPS接続で安全なアプリ用ドメイン「.app」--早期登録を受付開始 - CNET Japan
仕組み
結論: HSTSのPreload Listという技術を使っている.
HSTS
HSTS(HTTP Strict Transport Security)はHTTPでアクセスしてきたユーザ(HTTPクライアント)にHTTPSでのアクセスを強制するための技術である.対応しているWebサイトでは,HTTPレスポンスのヘッダに Strict-Transport-Security: xxx
が付与されている.Qiitaの場合はstrict-transport-security: max-age=2592000
が設定されている.RFC 6797で定義されている.
参考: Strict-Transport-Security - HTTP | MDN
FacebookはHSTS Preloadがレスポンスヘッダに含まれている.
Preload List
Preload ListはRFC 6797の中で定義されている.サイトの管理者は事前に定義したHSTSポリシーをpre-loaded listとよばれるリストにもたせることができる.このリストは,ブラウザがルート認証局の証明書を持つのと同様に,ブラウザに埋め込まれている.これはBootstrap MITMの脆弱性(後述)からの保護に役立つ.
Preload Listに含まれているドメインは,初回にWebブラウザでHTTPアクセスした場合もHTTPSアクセスを強制される.これにより,初回からHTTPSでの通信を行える.
FacebookはブラウザからHTTPでアクセスすると,ブラウザの内部でHTTPSへリダイレクトが行われる.Status Codeは307 Internal Redirectになる.
以下は,MozillaのPreload Listの一部である.5/12の段階でファイル全体は95377行ある.
$ curl -s https://hg.mozilla.org/mozilla-central/raw-file/tip/security/manager/ssl/nsSTSPreloadList.inc | head -20
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*****************************************************************************/
/* This is an automatically generated file. If you're not */
/* nsSiteSecurityService.cpp, you shouldn't be #including it. */
/*****************************************************************************/
#include <stdint.h>
const PRTime gPreloadListExpirationTime = INT64_C(1600956010611000);
%%
0--1.de, 1
0-1.party, 1
0-24.com, 1
0-24.net, 1
000321365.com, 1
0007552.com, 1
000a1.com, 1
000a2.com, 1
例えば,facebook
が含まれているドメインの一覧は19件ある.
$ curl -s https://hg.mozilla.org/mozilla-central/raw-file/tip/security/manager/ssl/nsSTSPreloadList.inc | grep facebook
apps.facebook.com, 0
business.facebook.com, 0
code.facebook.com, 0
connect.facebook.net, 1
developers.facebook.com, 0
facebook-atom.appspot.com, 1
facebook.ax, 1
facebook.com, 0
m.facebook.com, 1
mbasic.facebook.com, 0
mtouch.facebook.com, 0
pixel.facebook.com, 0
research.facebook.com, 0
secure.facebook.com, 0
t.facebook.com, 0
tablet.facebook.com, 0
touch.facebook.com, 0
upload.facebook.com, 0
www.facebook.com, 0
ChromiumのPreload Listは5/22の段階で110787行ある.
$ curl -s https://raw.githubusercontent.com/chromium/chromium/master/net/http/transport_security_state_static.json | tail
{ "name": "briellenj.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
{ "name": "blainecosheriff-ok.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
{ "name": "almaarkansas.gov", "policy": "public-suffix-requested", "mode": "force-https", "include_subdomains": true },
// END OF ETLD-OWNER REQUESTED ENTRIES
// To avoid trailing comma changes from showing up in diffs, we place a
// single entry at the end.
{ "name": "hstspreload.org", "policy": "custom", "include_subdomains": true, "mode": "force-https" }
]
}
Facebookを含むドメインは22件ある.よく見るとfacebooktsukaikata
という文字列を含むドメインもある.
$ curl -s https://raw.githubusercontent.com/chromium/chromium/master/net/http/transport_security_state_static.json | grep 'facebook'
"name": "facebook",
// Facebook would like to have pinning enforced on (*.)facebook.com and
"name": "facebook.com", "policy": "custom",
"mode": "force-https", "pins": "facebook", "include_subdomains_for_pinning": true
{ "name": "www.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "m.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "tablet.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "secure.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "pixel.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "apps.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "upload.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "developers.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "touch.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "mbasic.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "code.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "t.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "mtouch.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "business.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "research.facebook.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
"mode": "force-https", "pins": "facebook", "include_subdomains_for_pinning": true
{ "name": "www.messenger.com", "policy": "custom", "mode": "force-https", "include_subdomains": true, "pins": "facebook" },
{ "name": "facebook-atom.appspot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
{ "name": "facebook.ax", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
{ "name": "facebooktsukaikata.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
{ "name": "connect.facebook.net", "policy": "custom", "mode": "force-https", "include_subdomains": true },
.appドメインと.devドメインはトップレベルドメインとして登録されている.
$ curl -s https://raw.githubusercontent.com/chromium/chromium/master/net/http/transport_security_state_static.json | egrep '("dev"|"app")'
{ "name": "app", "policy": "public-suffix", "mode": "force-https", "include_subdomains": true },
{ "name": "dev", "policy": "public-suffix", "mode": "force-https", "include_subdomains": true },
どちらのPreload Listもソースコードと同封されていた.つまり,ユーザはビルド済みWebブラウザに内包されるPreload ListをもとにHSTSを利用していることになる.
Bootstrap MITMへの脆弱性
MITM(man-in-the-middle, 中間者攻撃)の説明は割愛する.RFCのBootstrap MITM Vulnerabilityに説明がある.
Bootstrap MITMの脆弱性は,未知のHSTSホスト(HSTSに対応したWebサーバ)へユーザーがhttpを使って,アドレスを入力してアクセスするか,リンクに従ってアクセスする場合に発生する.原因は,HTTPクライアント(Webブラウザやアプリケーション)が最初に接続先WebサーバとHTTPの通信を試みることにある.攻撃者によりHTTPの通信が改変された場合,ユーザは気づかないうちに攻撃者の用意した攻撃サイトへ誘導されてしまう.
HTTPS対応サイトでも初回にHTTPでアクセスされた場合(例: URLバーへアドレスを直接入力),ホスト(サーバ)までの経路は平文でやり取りされる.つまり,通信が暗号化により保護されない.よって,平文でやり取りされている通信は中間者攻撃により盗聴や改ざん,なりすましや否認の恐れがある.
ツール群の対応
curl
巨大なHSTS Preload Listを内包するのは,多くの使用者に好ましくないのでオプションでPreload Listを指定できる実装がすすめている.現段階ではメインストリームへマージされていない.curl 7.7.0でも確認済み.
- curl - Roadmap
- HTTP Strict Transport Security (HSTS) using libhsts by zagor · Pull Request #2682 · curl/curl
wget
1.99.2でChromium用のHSTS Preload List用のオプションが追加された.
1.99.2をビルドしたところ以下のオプションが確認できた.
$ wget --help | grep hsts
--hsts Use HTTP Strict Transport Security (HSTS).
--hsts-file Set file for HSTS caching. (default: ~/.wget-hsts)
--hsts-preload Use HTTP Strict Transport Security (HSTS).
[Not built with libhsts, so not functional]
--hsts-preload-file Set name for the HSTS Preload file (DAFSA format).
[Not built with libhsts, so not functional]
HSTS Preload ListへWebサイトを追加
- .devドメインや.appドメイン
- 既にPreload Listに含まれている為,対処は不要
- その他のドメイン
-
Strict-Transport-Security
ヘッダにpreloadオプションを付与 - https://hstspreload.org/ で申請
-
Preload Listに対応した主要サービス
- Twitter(twitter.com)
- Facebook(facebook.com)
- GitHub(github.com)
- YouTube(youtube.com)
- Slack(slack.com)
- WordPress.com(wordpress.com)
- Tumblr(tumblr.com)
- Cybozu(cybozu.com)
- Amazon(www.amazon.co.jp)
- Airbnb(www.airbnb.jp)
- Pinterest(pinterest.jp)
- Instagram(www.instagram.com)
(2020/06/24追記) govドメインもHSTS Preload Listへ
govドメインを全部HSTS Preloadに入れるアナウンス。2020年9月1日から新規ドメインは自動的にPreloadに入れ、将来的にgovのTLD全部を登録する予定。https://t.co/lcSQE0FXHfはいつになるのやら。 / “Making .gov More Secure by Default | DotGov” https://t.co/mUmDugFGwe
— Shigeki Ohtsu (@jovi0608) June 24, 2020
米国政府系サイトに使われるTLDであるgovもappやdevと同様にHSTS Preload Listに含まれるという.
(2020/10/06追記) newドメインもHSTS Preload Listへ
【自分用メモ】.newはTLDごと、HSTSプリロード済み。// Status: new is currently preloaded. - HSTS Preload List Submission https://t.co/FTkY5yTdjc
— Yasuhiro Morishita (@OrangeMorishita) July 27, 2020
新たなドメイン .new
がHSTS Preload Listに追加された.
その他のドメイン
.play
.youtube
.google
.gmail
.chrome
.foo
.android
.search
[例外] IPアドレス
Cloudflareの提供するパブリックDNS 1.0.0.1
がHSTS Preload Listに含まれていた.
(2025/05/09 追記) HSTS Preload Listが非推奨に
Xで以下のツイートを見て知った.
Many browsers (Chrome, Safari) will automatically upgrade all HTTP navigations to HTTPS, regardless of the domain's HSTS policy. HSTS preloading only provides value when these upgrades fail in the presence of an active attacker. The benefits provided by HSTS preloading are minimal compared to the benefits provided by HSTS. While HSTS is recommended, HSTS preloading is not recommended.
参考資料
- Strict-Transport-Security - HTTP | MDN
- HTTP Strict Transport Security - The Chromium Projects
- HSTS Preload List Submission
- HTTP Strict-Transport-Security (HSTS) - Qiita
- HSTS option on .dev domains - Feedback / Usage & Design - Cloudflare Community
- Google makes HTTPS encryption mandatory for its 45 new TLDs