HSTS(HTTP Strict Transport Security)- HTTPSを強制する最後の砦
これは何?
HSTS(HTTP Strict Transport Security)は、ブラウザに「このサイトは必ずHTTPSでアクセスせよ」と指示するセキュリティヘッダーです。一度HSTSヘッダーを受信したブラウザは、指定期間中、そのドメインへのすべてのアクセスを自動的にHTTPSに変換します。
HSTSヘッダーは、以下の形式でHTTPSレスポンスに含めます:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
この設定は「今後1年間(31536000秒)、このドメインとすべてのサブドメインは必ずHTTPSでアクセスせよ。HSTSプリロードリストに登録することを許可する」という意味です。
なぜ重要なのか
HTTPSを導入しても、以下のような脆弱性が残ります:
1. 最初のアクセスはHTTPの可能性
ユーザーがアドレスバーにexample.comと入力すると、ブラウザはまずhttp://example.comにアクセスします。サーバーがhttps://example.comにリダイレクトしますが、この最初のHTTPリクエストは平文で送信され、盗聴や改ざんのリスクがあります。
2. SSLストリッピング攻撃
攻撃者が中間者となり、HTTPSをHTTPに降格させる攻撃です:
- ユーザーが
http://bank.comにアクセス - 攻撃者がHTTPSリダイレクトを遮断し、HTTPのまま返す
- ユーザーはHTTPでログイン情報を送信し、攻撃者に盗まれる
HSTSがあれば、ブラウザは過去の記録から「このサイトはHTTPSのみ」と知っているため、HTTPリクエストを送信せず、最初からHTTPSでアクセスします。
3. ユーザーのミスタイプ
ユーザーがhttp://bank.comとブックマークしていたり、古いリンクをクリックした場合、HTTPでアクセスされる可能性があります。HSTSがあれば、ブラウザが自動的にHTTPSに変換します。
攻撃の仕組み
SSLストリッピング攻撃の詳細
2009年に発表されたこの攻撃は、HTTPSの普及期に大きな脅威でした:
- 準備: 攻撃者が公衆Wi-Fiなどで中間者攻撃の体制を整える(ARPスプーフィングなど)
- 最初のHTTPリクエスト: ユーザーが
http://example.comにアクセス - リダイレクトの遮断: サーバーは
https://example.comにリダイレクトしようとするが、攻撃者が介入 - HTTPのまま維持: 攻撃者がユーザーにはHTTPのまま応答し、サーバーにはHTTPSで中継
- 盗聴・改ざん: ユーザーとサーバー間の通信を、攻撃者が平文で読み書きできる
HSTSがある場合、ブラウザは過去の訪問記録から「このサイトはHTTPSのみ」と知っているため、ステップ2でHTTPリクエストを送らず、最初からHTTPSでアクセスします。
Cookie盗聴攻撃
HSTSにはincludeSubDomainsオプションがあり、これがないとサブドメインが狙われます:
- メインドメイン
example.comはHTTPS + HSTS - サブドメイン
blog.example.comはHTTPSだがHSTSなし - 攻撃者が
http://blog.example.comへのアクセスを中間者攻撃 - メインドメインのCookieがサブドメインに送信され、盗聴される
includeSubDomainsを設定すれば、すべてのサブドメインもHSTSで保護されます。
実際の被害事例
Moxie Marlinspike氏のsslstrip(2009年)
セキュリティ研究者のMoxie Marlinspike氏が、SSLストリッピング攻撃を実装した「sslstrip」ツールを公開しました。このツールは、公衆Wi-Fiで簡単にHTTPS通信を盗聴できることを実証し、HSTS開発の契機となりました。
中国のGreat Cannon攻撃(2015年)
中国政府の検閲システムが、Baiduの広告スクリプトを改ざんし、GitHubへのDDoS攻撃を実行しました。Baiduのスクリプトが一部HTTPで配信されていたため、中間で改ざん可能でした。HSTSがあれば、このような攻撃を防げた可能性があります。
Wi-Fiパイナップル攻撃
ハッカーが「Wi-Fi Pineapple」という装置を使い、公衆Wi-Fiを模倣して中間者攻撃を行う事例が多発しています。HTTPSサイトでも、HSTSがなければSSLストリッピングで攻撃されます。2018年の調査では、主要空港やカフェのWi-Fiで、こうした攻撃が実際に観測されています。
Nyambushでの検出内容
Nyambushは、以下の項目をチェックします:
- HSTSヘッダーの存在: HTTPSレスポンスに
Strict-Transport-Securityヘッダーがあるか - max-ageの長さ: 推奨は1年以上(31536000秒)
- includeSubDomainsの有無: サブドメインも保護されているか
- preloadの有無: HSTSプリロードリストへの登録準備ができているか
- HTTPでのアクセス: HTTPからHTTPSへ正しくリダイレクトされるか
スキャン結果では、HSTSが未設定の場合、Webサーバーの設定例を提示します。
対策方法
1. HSTSヘッダーの追加
Nginxの場合
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL証明書の設定(省略)
# HSTSヘッダー(1年間、サブドメイン含む、preload対応)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
root /var/www/html;
index index.html;
}
}
重要: alwaysを付けないと、エラーレスポンス(404、500など)でヘッダーが送信されません。
Apacheの場合
<VirtualHost *:443>
ServerName example.com
SSLEngine on
# SSL証明書の設定(省略)
# HSTSヘッダー
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
DocumentRoot /var/www/html
</VirtualHost>
mod_headersモジュールが必要です:
sudo a2enmod headers
sudo systemctl restart apache2
Node.js/Expressの場合
const express = require('express');
const helmet = require('helmet');
const app = express();
// helmetでHSTSを有効化
app.use(helmet.hsts({
maxAge: 31536000, // 1年
includeSubDomains: true,
preload: true
}));
app.get('/', (req, res) => {
res.send('Hello, secure world!');
});
app.listen(443);
2. 段階的な導入
いきなり1年間(max-age=31536000)に設定すると、問題が起きた時に後戻りできません。段階的に導入します:
ステップ1: 短期間でテスト
Strict-Transport-Security: max-age=300; includeSubDomains
5分間(300秒)HSTSを有効にし、サイトが正常に動作するか確認します。
ステップ2: 1週間に延長
Strict-Transport-Security: max-age=604800; includeSubDomains
1週間(604800秒)問題なく動作することを確認します。
ステップ3: 1年間に設定
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
問題がなければ、1年間に設定し、preloadオプションも追加します。
3. HSTSプリロードリストへの登録
HSTSには「初回訪問時は無防備」という問題があります。ユーザーが一度もそのサイトを訪れたことがなければ、HSTSヘッダーを受信しておらず、最初のアクセスはHTTPになる可能性があります。
この問題を解決するのが、HSTSプリロードリストです。Chrome、Firefox、Safari、Edgeなどのブラウザに、あらかじめHSTS対応サイトのリストを組み込むことで、初回訪問時から自動的にHTTPSでアクセスします。
登録条件
- 有効なHTTPS証明書
- すべてのHTTPトラフィックをHTTPSにリダイレクト
- すべてのサブドメインでHTTPSをサポート
- HSTSヘッダーに以下を含める:
max-ageが31536000(1年)以上includeSubDomainspreload
登録手順
- 上記条件を満たしているか確認
- https://hstspreload.org/ にアクセス
- ドメイン名を入力し、チェック
- 問題がなければ送信
登録後、数ヶ月でChromiumのソースコードに追加され、各ブラウザに配布されます。
注意点
プリロードリストからの削除は非常に困難です。 一度登録すると、削除申請から実際に各ブラウザから消えるまで数ヶ月〜1年かかります。すべてのサブドメインで永続的にHTTPSをサポートできる確信がない限り、登録すべきではありません。
特に、以下のような場合は注意:
- サブドメインで古いアプリケーションやデバイスが動作している
- HTTPのみをサポートする必要のあるレガシーサービスがある
- サブドメインの管理が分散している大企業
4. includeSubDomainsの注意点
includeSubDomainsを設定すると、すべてのサブドメインでHTTPSが必須になります。以下を確認してください:
- すべてのサブドメインにSSL証明書がインストールされているか
- 開発環境やステージング環境のサブドメイン(
dev.example.comなど)もHTTPS対応か - 古いアプリケーションがHTTPのみで動作していないか
問題がある場合は、includeSubDomainsを外すか、問題のあるサブドメインに対してワイルドカード証明書を導入します。
5. テストと検証
設定後、以下を確認します:
# HSTSヘッダーを確認
curl -I https://example.com | grep Strict-Transport-Security
# 期待される出力
# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
ブラウザでアクセスし、開発者ツール(F12)→「ネットワーク」タブでレスポンスヘッダーを確認します。
また、https://hstspreload.org/ でドメインをチェックし、プリロード登録の準備ができているか確認します。
まとめ
HSTSは、HTTPSを導入した後の「最後の穴」を塞ぐ重要な対策です。SSLストリッピング攻撃や、ユーザーのミスタイプによるHTTPアクセスを防ぎ、完全なHTTPS化を実現します。
設定は簡単で、HTTPSレスポンスに1行のヘッダーを追加するだけです。ただし、includeSubDomainsやpreloadリスト登録は慎重に行う必要があります。段階的にmax-ageを延ばし、問題がないことを確認してから、最終的に1年間に設定しましょう。
HTTPS + HSTSの組み合わせで、ウェブサイトの通信セキュリティは大幅に向上します。Nyambushの無料スキャンで、あなたのサイトのHSTS設定を確認してみてください。