Burp の TLS Pass Through 設定の使い所と仕組み
こんにちは、SSTでWeb脆弱性診断用のツール(スキャンツール)開発をしている坂本(Twitter, GitHub)です。
iOSやAndroidで Burp のProxy設定をすると、いくつかのアプリで通信エラーになってしまうことがあります。
例として以下のような操作があります。
- アプリのインストール (AppStore や Google Play の操作)
- 課金処理
Burp では TLS Pass Through を設定することでこれらの通信エラーを回避できることがあります。
今回はこの機能について PortSwigger 社のブログ記事を参考に解説します。
- SSL pass through in Burp | Blog – PortSwigger
- https://portswigger.net/blog/ssl-pass-through-in-burp
- ※このブログ記事では “SSL” と表記していますが、2021-07時点ではBurpの画面上 “TLS” と表記されていますので、本記事では “TLS Pass Through” として統一します。
動作確認バージョン:
- Burp Suite Community Edition v2021.5.1
TLS Pass Through の設定方法
- TLS Pass Through 設定が必要なホストを確認。
Dashboard
タブ →Event log
を確認し、”The client failed to negotiate a TLS connection to (ホスト名):443: Remote host terminated the handshake” のようなログがあれば、TLS Pass Through により改善できる可能性があります。
Proxy
タブ →Options
タブ →TLS Pass Through
設定でAdd
ボタンをクリックし、問題が発生しているホスト名, オプションでポート番号を入力して追加。
“The client failed to negotiate a TLS connection to…” が大量に発生するようであれば、 “Automatically add entries on client TLS negotiation failure” にチェックを入れると便利です。
このエラーが発生したホストについて、自動で Pass Through 対象に追加するようになります。(Proxy listener の再起動は不要)
TLS Pass Through 対象のホストとの通信については、”HTTP history” に通信ログが出てこないことに注意してください。
通信内容が見れなくても問題ないサーバを対象に追加してください。
例として以下があります。
- AppStore
- Google Play
- 課金処理で通信する決済系サーバ
- その他、自分たちが開発していない/診断対象でないアプリなど
では TLS Pass Through とは結局どういう仕組でしょうか?
なぜこれによりHTTPS通信が正常に動くようになるのでしょうか?
なぜTLS Pass Through 対象にするとHTTPS通信の中身(平文) が見れなくなるのでしょうか?
これらの疑問に答えるために、まず Burp が HTTPS 通信の内容(平文)を見れる仕組みを解説します。
なぜBurp は HTTPS 通信の内容(平文)を見ることができるのか?
https://
のTLS通信はブラウザとサーバ間で暗号化されており、本来なら暗号化する前の平文を通信経路で見ることはできません。
+---------------------+
| browser/http-client |<-+
| (plain http message)| |
+---------------------+ |
|
+--- TLS(= encrypted) ------+
|
| +---------------------+
+->| https-web-server |
| (plain http message)|
+---------------------+
Burp は Proxy という性質を利用し、自らが接続先のWebサーバとして振る舞います。
Webサーバとして振る舞うということは、そこで暗号化通信を復号し、暗号化する前の平文を取り出せることを意味します。
Burp は平文のHTTP通信ログを取り出し、記録します。
記録した後は本来のWebサーバに接続し、もう一度HTTP通信をTLSで暗号化して中継しています。
+---------------------+
| browser/http-client |<-+
| (plain http message)| |
+---------------------+ |
|
+--- TLS(= encrypted) ------+
|
| +-------------------------------------------+
+->| Burp's internal https-web-server |
| (plain http message) --+--> "HTTP history"|
| | |
+------------------------|------------------+
|
+--- TLS(= encrypted) ------+
|
| +---------------------+
+->| https-web-server |
| (plain http message)|
+---------------------+
以上が、Burp でHTTPS通信の中身、すなわち暗号化する前の平文のHTTPメッセージを見ることができる仕組みです。
TLS Pass Through の仕組み
“Pass Through” という表現通り、TLS接続を素通しします。
Burp は Webサーバとして振る舞うことはせず、TLSの暗号化通信をそのまま実際のWebサーバに中継することに徹します。
+---------------------+
| browser/http-client |<-+
| (plain http message)| |
+---------------------+ |
|
+--- TLS(= encrypted) ------+
|
| +-------------------------------+
| | Burp pass through tls traffic |
| | |
+->-<--- TLS(= encrypted) -------->-<--+
| | |
+-------------------------------+ |
|
+--- TLS(= encrypted) -----------------+
|
| +---------------------+
+->| https-web-server |
| (plain http message)|
+---------------------+
TLS通信を復号しないため、平文のHTTPメッセージを取得することはできません。
そのため TLS Pass Through 対象の通信は “HTTP history” に表示されなくなります。
ここまでで Burp がHTTPS通信の内容を見ることができる仕組みと、TLS Pass Through の仕組みが分かりました。
しかしまだ疑問はたくさんあります。
- なぜ TLS Pass Through が必要なのでしょうか?
- TLS Pass Through を使わない状態で、 “The client failed to negotiate a TLS connection to …” が発生するのはなぜでしょうか?
- なぜ TLS Pass Through の対象にするとこのエラーが解決するのでしょうか?
これらの疑問に答えるため、証明書のピンニングについて解説します・・・が、その前提知識としてサーバ証明書の検証について解説します。
TLSにおけるサーバ証明書の検証
せっかく通信を暗号化しても、通信する相手が偽物であれば意味はありません。
TLSではサーバ証明書を検証することで、通信相手が本物であることを保証します。
- ブラウザがサーバに接続し、TLS通信の初期化フェーズ*1を開始します。
- このときにブラウザからサーバに送る「挨拶」データを、TLSでは “ClientHello” メッセージと呼んでいます。
- ClientHello を受け付けたサーバは、サーバ側のTLS設定(ServerHello)とサーバ証明書(Certificate)をブラウザに返します。
- 本物のWebサーバであれば、一般的な認証局(CA: Certificate Authority) で署名・発行されたサーバ証明書を返します。
- サーバ証明書を受け取ったブラウザは、ブラウザやOSにインストール済みの信頼できる認証局*2で発行された証明書か検証します。
- 信頼できるCAが署名・発行した証明書であると確認できれば検証は成功です。接続先は本物のWebサーバであると判断し、TLS通信を続けます。
- もし信頼できるCAが署名・発行したと確認できなかった場合は、検証失敗となります。ブラウザはエラー画面を表示し、TLS通信をそこで終了します。実際のHTTP通信は行いません。
HTTPSのWebサーバをセットアップする際は、必ず秘密鍵と公開鍵のペアを作成し、公開鍵を認証局に送って証明書を署名・発行してもらう必要があります。
それは、上記のように「接続先が本物のWebサーバか、なりすました偽物ではないか?」をブラウザやHTTPクライアントが検証するためです。
ここでBurpがHTTPS通信内容を見る仕組みを思い出してください。
Burp はまさに「Webサーバになりすました偽物」として振る舞い、TLS暗号通信を復号しています。
+---------------------+
| browser/http-client |<-+
| (plain http message)| |
+---------------------+ |
|
+--- TLS(= encrypted) ------+
|
| +-------------------------------------------+
+->| Burp's internal https-web-server |
| (plain http message) --+--> "HTTP history"|
| | |
+-----------------------(...)---------------+
BurpがWebサーバとして代わりに振る舞うとなると、Burp自身がサーバ証明書を提示する必要があります。
Burpは独自の認証局を内蔵しており、アクセスしてきたホスト名に応じて動的にサーバ証明書を生成しています。
つまり Burp が提示するサーバ証明書は、Burp 独自の認証局により署名・発行されたものになります。
このサーバ証明書をブラウザ側で検証成功とするためには、Burp 独自の認証局の証明書(= “CA証明書”) をOSやブラウザにインストールし、信頼する必要があります。
残念がら、昔から、そして2021年時点でも、最初から Burp 独自のCA証明書をインストール・信頼しているOSやブラウザはありません。
そのため Burp を通して HTTPS 通信の中身を見ようとするなら、証明書検証を成功させるために Burp の CA証明書を手動でインストールして信頼する必要があります。
Burp の CA証明書をインストールしていないと、ブラウザからすると「見ず知らずの認証局により発行されたサーバ証明書が提示された・・・怪しいな、これ本当に接続先のWebサーバかな?」となり、そこで通信を打ち切ります。 結果としてブラウザ上ではエラー画面が表示され、 https://
のWebサイトを利用できなくなります。
Burp のCA証明書をインストールして信頼するための具体的な方法については、 PortSwigger 社が公開している以下の資料を参照してください。
- Installing Burp’s CA certificate – PortSwigger
- Installing Burp’s CA Certificate in an iOS Device – PortSwigger
- Installing Burp’s CA Certificate in an Android Device – PortSwigger
Burp のCA証明書をインストールして信頼すれば、HTTPS通信は正常に通信できて、平文のHTTP通信も見れるので一安心・・・と行きたいところですが、そうはなりませんでした。
Webの世界で、セキュリティ向上を目的とした「証明書のピンニング」という技術が登場します。
この技術が、Burpが生成したサーバ証明書の検証を失敗させ、TLS通信エラーを引き起こす原因となるのです。
証明書のピンニング
証明書のピンニングとは、特定のサーバ証明書や認証局から発行された証明書のみ許可するよう固定(Pin留め, Pinning)する仕組みです。
一時期、認証局が攻撃されて証明書の信頼性が揺らぐ時期がありました。
認証局を使った検証を用いず、アプリ自身が知っているサーバ証明書やCA証明書のみ検証を成功させる。
それにより認証局の信頼性の影響を受けずにセキュリティを強化できると期待され、証明書のピンニングが登場しました。
サーバ証明書の誤発行, 証明書の危殆化, 中間者攻撃*3 に対しても効果があると期待されました。
証明書をピンニングするためには、HTTPクライアント(ブラウザやスマホアプリ)側が予めサーバ証明書やその発行元となる認証局の情報を知っている必要があります。
そのため、不特定多数と通信するブラウザではピンニングは向いていません。
一方で特定のアプリケーションのみを実行するスマホアプリでは、限定された少数のサーバとのみ通信するので、ピンニングも組み込みやすいです。
例として 『Androidアプリのセキュア設計・セキュアコーディングガイド』【2020年11月1日版】(一般社団法人 日本スマーフォンセキュリティ協会) では「ピンニングによる検証の注意点と実装例」と題してピンニングについて解説しています。
ピンニングが使われだすと、以下のようなデメリットも見えてきました。
- アプリ側とサーバ側で証明書情報を同期させる必要がある。
- 証明書を失効させるための方法が確立していない。
結果として、2021年時点では証明書のピンニングは非推奨の技術となっています。
以下の参考資料でも明確に非推奨が唱えられています。
ここまでで前提知識が全て揃いました。
ようやく TLS Pass Through がなぜ有効か、の疑問を解決します。
証明書ピンニングと Burp の TLS Pass Through
証明書ピンニングが行われているアプリ(HTTPS クライアント) が Burp Proxy を介してHTTPS 通信するとどうなるでしょうか?
- Burpは実際のWebサーバとして振る舞い、Burpが生成したサーバ証明書を返します。
- アプリ側では証明書ピンニングにより、本来のWebサーバの証明書以外は検証失敗になります。
- → これにより、Burpを通したHTTPS通信が失敗します。
- Burp 上では “The client failed to negotiate a TLS connection to …” が発生, アプリ側では通信エラー。
証明書ピンニングを行っていると、OSやブラウザにインストール済みのCA証明書を検証で使わないケースがある、というのがポイントになります。*4
このため OSやブラウザに Burp のCA証明書をインストールして信頼していたとしても、サーバ証明書の検証では参照されず、結果として検証は失敗するケースが発生します。
TLS Pass Through の対象にすると、以下のようになります。
- BurpはTLS通信を中継するだけなので、実際のWebサーバがTLS通信を処理し、本物のサーバ証明書がアプリ側に返されます。
- アプリ側では証明書ピンニングにより、本来のWebサーバの証明書について検証成功となります。
- → これによりアプリ側ではHTTPS通信に成功します。一方で Burp ではHTTPS通信の中身は見れなくなります。
TLS Pass Through の対象とすることで一部のHTTPS通信エラーを回避できるメカニズムは、以上になります。
非推奨になったとはいえ、まさにBurpが行っているような中間者攻撃を防げるのが証明書ピンニングのメリットです。
これを優先するようなアプリとして、スマホアプリのマーケットプレイスや決済系の通信が考えられます。
AppStore や Google Play, 一部のSNSアプリなどはこの点を重視して証明書ピンニングを使っているのではないかと筆者は推測しています。
TLS Pass Through の対象にすると通信エラーがなくなるのも、その推測を裏付けていると考えています。
ここまでの疑問について回答してみます。
- Q1: なぜ TLS Pass Through が必要なのでしょうか?
- A1: TLS通信を復号せずにそのままpass through で中継しないとHTTPクライアント/サーバのどちらかでエラーとなるケースがあるためです。原因の一つとして証明書ピンニングが考えられ、TLS Pass Through 設定をしないと HTTPクライアント側で証明書検証エラーになり、正常にHTTPS通信できないことがあります。
- Q2: TLS Pass Through を使わない状態で、 “The client failed to negotiate a TLS connection to …” が発生するのはなぜでしょうか?
- A2: いくつか原因は考えられますが、証明書ピンニングにより Burp 独自のCAが署名・発行したサーバ証明書に対して検証失敗となり、HTTPクライアント側から通信を切断している可能性があります。
- Q3: なぜ TLS Pass Through の対象にするとこのエラーが解決するのでしょうか?
- A3: 証明書ピンニングが原因の場合、TLS Pass Through によりHTTPクライアントからのTLS通信がそのまま本物のWebサーバに中継され、本物のサーバ証明書がHTTPクライアントに返されることで検証成功するためと思われます。代わりにBurp ではTLS通信で暗号化するまえの平文のHTTP通信をみることができなくなります。
まとめ
長くなりましたが、以下のトピックを網羅できました。
- Burp がHTTPS通信の中身を見れる仕組み
- Burp の TLS Pass Through の仕組み
- TLSにおけるサーバ証明書の検証と Burp のCA証明書の関係
- 証明書ピンニング
これらの知識を元に、ようやく「なぜ TLS Pass Through を使うのか?」「なぜ TLS Pass Through で HTTPS 通信エラーが解消されるのか?」を説明できるようになったと思います。
簡単ではありますが、ポイントに絞って以下にまとめてみました。
- Burp は
https://
に対してWebサーバとして振る舞い、TLS通信の複合処理を行う。その際に Burp が生成したサーバ証明書をHTTPSクライアント(ブラウザ, スマホアプリ等)に提示する。 - TLS通信ではサーバが提示してきたサーバ証明書を使って「本物のWebサーバか?」を検証する。
- Burp のCA証明書をインストールしないと、Burpが生成したサーバ証明書をブラウザ側で検証失敗し、TLS通信ができない。
- Burp の TLS Pass Through を使うと、TLS通信を実際のWebサーバに中継するだけになる。
- HTTPSクライアントに返されるサーバ証明書は、実際のWebサーバのものになる。
- Burp はTLS通信を復号しなくなるので、HTTPS通信の中身は見れなくなる。
- 証明書ピンニングを用いた HTTPS クライアントでは、Burp が生成したサーバ証明書を受け付けられない。
- TLS Pass Through の対象に追加し、本物のサーバ証明書を受け取れるようにしないと通信エラーとなる。
- 中間者攻撃への防御を特に重視するスマホアプリで使われていると推測 : マーケットプレイス系のアプリや決済通信、一部のSNSアプリなど。
「Burpを通したHTTPS通信でエラーが起きたら、TLS Pass Through を試してみるといい」のように、中身が分からないまま闇雲に設定を弄っても良いトラブルシュートはできません。
技術的な仕組みが分かれば、TLS Pass Through で解決する問題・しない問題の切り分けにも役立ち、効果的なトラブルシュートにつながります。
Burpを使うときのトラブルシュートで役立てば幸いです。
TLSの仕組みや認証局、証明書の話は奥が深いです。
より詳しく知りたい・興味がある方向けに以下の書籍を推薦します。
*1:ネゴシエーション, negotiation とも呼ぶ
*2:CA : Certificate Authority
*3:途中の通信経路でなりすまして通信内容を取得したり、改ざんする攻撃。技術的にはまさにBurpがHTTPS通信にしていることと同じになる。
*4:すべてのケースで使わないか、というと、ピンニング処理をどう実装するかに依存してくると思います。