中間者攻撃(Man-in-the-Middle Attack)
概要
中間者攻撃(Man-in-the-Middle Attack) は、通信を行う二者の間に攻撃者が割り込み、やり取りされるデータを傍受・改ざんする攻撃手法です。攻撃者はクライアントに対してサーバーのふりをし、サーバーに対してクライアントのふりをすることで、双方が直接通信していると信じている状態を維持しながら通信内容を操作します。
MitM 攻撃は古くから知られたカテゴリの攻撃であり、現代の HTTPS 通信においてもいくつかの条件が揃えば成立します。暗号化されていない HTTP 通信はもちろん、不正な認証局(CA)による証明書発行、ユーザーによる証明書警告の無視、TLS 実装の脆弱性など、信頼の連鎖が崩れるポイントが攻撃の起点になります。
防御の基盤は TLS/SSL 証明書による通信の暗号化とサーバー認証です。これに加えて HSTS による HTTPS の強制、Certificate Transparency による不正証明書の検出、DNSSEC による DNS 応答の改ざん防止が多層的な防御を形成します。
仕組み
MitM 攻撃はネットワーク経路上への割り込みを起点とし、SSL ストリッピングや TLS インターセプトといった手法で暗号化通信を無力化します。
攻撃の基本構造
通常の HTTPS 通信では、クライアントとサーバーが TLS ハンドシェイクを通じて暗号化された通信路を確立します。MitM 攻撃者はこの通信路の確立前、または確立の過程に介入します。
攻撃が成立するには、攻撃者がクライアントとサーバーの間のネットワーク経路上にいる必要があります。攻撃者がネットワーク上の位置を確保する手段には次のようなものがあります。
- 公衆 Wi-Fi のアクセスポイントを偽装する(Evil Twin 攻撃)
- ARP スプーフィングでローカルネットワーク内のトラフィックを自分に向ける
- DNS キャッシュポイズニングで名前解決を乗っ取る
- BGP ハイジャックで経路情報を操作する
ネットワーク上の位置を確保した攻撃者は、通信を中継する形で傍受します。暗号化されていない HTTP 通信であれば、認証情報やセッション Cookie をそのまま読み取れます。
SSL ストリッピング
SSL ストリッピングは MitM 攻撃の代表的な手法の 1 つです。2009 年に Moxie Marlinspike が Black Hat DC で発表しました。
この攻撃は HTTPS そのものを破るのではなく、クライアントが HTTPS を使う機会を奪います。手順は次のとおりです。
- ユーザーが
http://example.comにアクセスする - 攻撃者がその HTTP リクエストを傍受する
- 攻撃者はサーバーに対して HTTPS で接続し、正規のレスポンスを取得する
- 攻撃者はレスポンス中の
https://リンクをhttp://に書き換えてユーザーに返す - 以降、ユーザーは HTTP でサイトを閲覧し続け、攻撃者はすべての通信を平文で傍受する
ユーザーのブラウザーには鍵マークが表示されず、URL バーも http:// のままですが、多くのユーザーはこの違いに気づきません。
HSTS はこの攻撃に対する有効な防御策です。ブラウザーが HSTS ポリシーを保持していれば、HTTP リクエストをネットワークに送出する前に内部で HTTPS に書き換えます。HSTS preload リストに登録されていれば、初回アクセスであっても SSL ストリッピングを防げます。
TLS インターセプト
攻撃者が TLS 通信自体に介入するパターンも存在します。攻撃者は自前の証明書を使ってクライアントとの TLS セッションを確立し、同時にサーバーとも別の TLS セッションを確立して、2 つのセッション間でデータを中継します。
この攻撃が成立する条件は限られています。攻撃者の証明書はクライアントのトラストストアに含まれる CA から発行されている必要があります。正規の公開 CA がドメイン所有者以外に証明書を発行することは通常ありません。ただし、次のケースでは攻撃が成立し得ます。
- CA が侵害され不正な証明書が発行される(2011 年の DigiNotar 事件では、
*.google.comを含む 531 枚の不正証明書が発行されました) - 企業の社内ネットワークで、端末にインストールされた独自ルート CA を使ってプロキシが TLS を復号する
- マルウェアが OS のトラストストアに独自の CA 証明書をインストールする
Certificate Transparency(CT)は、公開 CA が発行したすべての証明書を公開ログに記録する仕組みです。ドメイン所有者は自分のドメインに対して発行された証明書を監視でき、不正発行の早期検出が可能です。Chrome は 2018 年 4 月以降、CT ログに登録されていない証明書を信頼しません。
具体例
公衆 Wi-Fi での SSL ストリッピングと、CA 侵害による不正証明書発行の実際の事例を示します。
公衆 Wi-Fi での攻撃シナリオ
カフェの Wi-Fi に接続したユーザーが http://bank.example.com にアクセスするケースを考えます。攻撃者は同じネットワーク上で Evil Twin アクセスポイントを運用しています。
HSTS なしの場合、攻撃者は SSL ストリッピングを実行し、ユーザーのログイン認証情報を傍受できます。
HSTS ありの場合、ブラウザーは bank.example.com の HSTS エントリーを参照し、HTTP リクエストを送信する前に HTTPS に内部変換します。攻撃者が傍受できるのは暗号化された TLS トラフィックのみです。
HSTS preload リスト登録済みの場合、ユーザーが一度もサイトにアクセスしたことがなくても HTTPS が強制されます。
DigiNotar 事件(2011 年)
2011 年 7 月、オランダの CA である DigiNotar が侵害され、*.google.com を含む 531 枚の不正証明書が発行されました。イラン国内のユーザーに対する MitM 攻撃に使われたことが確認されています。この事件を受けて DigiNotar のルート証明書はすべてのブラウザーから削除され、DigiNotar は破産しました。
この事件は Certificate Transparency の標準化(RFC 6962、2013 年)を加速させた要因の 1 つです。
確認方法
openssl でサーバーの TLS 設定を確認するには次のコマンドを使います。
# TLS 1.3 での接続を確認
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null 2>/dev/null | grep -E "Protocol|Cipher"
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
TLS 1.3 で接続できない場合、サーバーが TLS 1.2 以下のみをサポートしている可能性があります。TLS 1.0 や 1.1 は RFC 8996(2021 年)で非推奨とされており、攻撃対象面を広げます。
証明書チェーンの完全性を確認するには次のコマンドを使います。
# 証明書チェーン全体を表示
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null
出力に中間証明書が含まれていない場合、AIA fetching に依存した不完全な設定です。
HSTS ヘッダーの設定を確認するには次のコマンドを使います。
curl -sI https://example.com | grep -i strict-transport-security
strict-transport-security: max-age=31536000; includeSubDomains; preload
ヘッダーが返らない場合、SSL ストリッピング攻撃に対して脆弱な状態です。
外部の視点からも確認したい場合は、Labee Dev Toolbox の SSL Cert API を使うと、外部の視点から見た結果を取得できます。
curl "https://labee.dev/api/ssl-cert?hostname=example.com"
レスポンスは次の形式で返ります。
{
"success": true,
"data": {
"hostname": "example.com",
"port": 443,
"reachable": true,
"status": 200
},
"error": null,
"meta": { "responseTime": 150 }
}
data.reachable が true であれば、外部から HTTPS 接続が成立しています。false の場合、証明書の期限切れや設定ミスなど、MitM 攻撃に対する防御が機能していない可能性があります。
よくある問題
MitM 攻撃への防御が不十分になるケースは、HSTS 未設定、証明書警告の無視、Mixed Content の残存が主な原因です。
HSTS 未設定による SSL ストリッピングへの脆弱性
HTTPS を有効にしていても、HSTS を設定していなければ SSL ストリッピング攻撃に対して脆弱です。HTTP から HTTPS へのリダイレクト(301)だけでは、最初の HTTP リクエストが傍受される余地が残ります。Strict-Transport-Security ヘッダーを設定し、可能であれば HSTS preload リストに登録します。
証明書警告の無視
自己署名証明書を使う開発環境や、期限切れの証明書を使うサイトにアクセスする際、ユーザーが証明書警告を無視する習慣をつけてしまうと、本番環境での MitM 攻撃時にも同様に警告を無視するリスクが高まります。開発環境でも mkcert などで OS のトラストストアに登録した証明書を使い、証明書警告を無視する運用を避けます。
企業プロキシによる TLS インターセプト
企業のセキュリティプロキシが TLS 通信を復号・検査する構成は、技術的には MitM と同じ仕組みです。プロキシの独自 CA 証明書が端末にインストールされ、すべての HTTPS 通信がプロキシ経由で復号されます。証明書ピンニングを使うアプリケーションはこの環境で接続に失敗することがあります。開発者は openssl s_client で取得できる証明書の Issuer を確認し、プロキシが介入しているか判別できます。
HTTP と HTTPS の混在コンテンツ
HTTPS ページ内で HTTP の画像やスクリプトを読み込む Mixed Content は、その HTTP リソースに対する MitM 攻撃を可能にします。攻撃者は HTTP 経由で読み込まれるスクリプトを差し替えることで、HTTPS ページ上でのコード実行を達成できます。Chrome は Mixed Content のうちスクリプトやフレームをデフォルトでブロックし、画像や動画については HTTPS への自動アップグレードを試みます。サイト全体のリソースを HTTPS で配信し、Content-Security-Policy: upgrade-insecure-requests ヘッダーの使用を検討します。
DNS キャッシュポイズニングとの組み合わせ
攻撃者が DNS 応答を偽装してユーザーを攻撃者のサーバーに誘導した場合でも、TLS 証明書の検証が正しく行われていれば攻撃は失敗します。攻撃者のサーバーは正規ドメインの有効な証明書を持っていないため、ブラウザーが証明書エラーを表示します。ただし、ユーザーが証明書エラーを無視すれば攻撃が成立します。DNSSEC を有効にすると DNS 応答の改ざん自体を防げます。