HTTPSのブラックボックスを覗き見る
現代のウェブトラフィックは、そのほとんどが暗号化されています。これはユーザーのプライバシーにとっては大きな勝利ですが、開発者にとっては大きな悩みの種となります。APIが不可解なエラーを返したり、モバイルアプリが予期しない動作をしたりしたとき、パケットを単純に「覗き見る」ことはできません。暗号文の壁をただ見つめることしかできないのです。だからこそ、内部で実際に何が起きているのかを確認する必要があるとき、私はまずmitmproxyを手に取ります。
Chromeの「ネットワーク」タブをさらに強力にしたものだと考えてください。ブラウザのリクエストを表示するだけでなく、実践的なWebセキュリティテストと同様に、モバイルアプリ、CLIツール、バックエンドのマイクロサービスなど、あらゆるソースからのトラフィックをインターセプトします。HTTP/2ストリームのデバッグでもWebSocketsの検査でも、mitmproxyを使えばデータフローを完全に制御できます。
5分で終わるセットアップ
mitmproxyを起動するのは驚くほど簡単です。独自のペネトレーションテスト環境に組み込むのも容易で、Pythonの依存関係を自動的に処理し、後のバージョン競合を防いでくれるパッケージマネージャーの使用をお勧めします。
1. インストール
macOSの場合、Homebrewを使うのが最もスムーズです。Linuxユーザーの場合、システム環境をクリーンに保つための標準的なツールであるpipxが最適です。
# macOS用
brew install mitmproxy
# Linux (Ubuntu/Debian用)
sudo apt update && sudo apt install mitmproxy
2. インターフェースの選択
mitmproxyには3つの形態があります。mitmproxyはクラシックなターミナルUI(TUI)を提供します。mitmwebはブラウザベースのダッシュボードを起動します。mitmdumpはHTTP版のtcpdumpのように動作します。私の仕事の90%において、何千ものリクエストをフィルタリングするにはターミナルインターフェースが最も高速です。
mitmproxy
プロキシはデフォルトでポート8080でリスニングを開始します。別のサービスがそのポートを使用している場合は、-p 8888のように変更できます。
3. トラフィックのルーティング
デバイスまたはブラウザの設定をlocalhost:8080に向けます。この時点では、HTTPサイトは読み込まれますが、HTTPSサイトでは「この接続はプライベートではありません」という警告が表示されます。これは、デバイスがプロキシの自己署名証明書を(正当な理由で)まだ信頼していないためです。
SSLインスペクションの設定(「魔法」の部分)
トラフィックを復号するために、mitmproxyはアクセスするサイトごとにダミーの証明書を生成します。デバイスがmitmproxyを信頼できる認証局(CA)として認識する必要があります。
CA証明書のインストール
プロキシを実行した状態で、ブラウザでmitm.itにアクセスします。このページはOSを検出し、適切な証明書のダウンロードリンクを提供します。
- Windows/macOS: 証明書をインストールし、「信頼されたルート証明機関」ストアに移動します。
- Android: Android 7.0以降、アプリはデフォルトでユーザーがインストールした証明書を無視します。この制限を回避するには、ルート化されたデバイスやパッチを適用したAPKが必要になる場合があります。
- iOS: プロファイルをダウンロードし、設定 > 一般 > 情報 > 証明書信頼設定に移動します。mitmproxyのスイッチを手動でオンにして「フル信頼」にする必要があります。
インフラセキュリティに関する注意点
チームでのテストのためにリモートサーバーでmitmproxyを実行する場合、公開したままにしないでください。保護されていないプロキシはすぐにボットに見つかり、悪意のあるトラフィックに利用されます。私は常に.htpasswdファイルを使用して強力な認証を設定しています。これを生成するには、toolcraft.appのパスワードジェネレーターを使用しています。これはクライアントサイドのツールであるため、キーやパスワードがブラウザの外に出ることはなく、機密性の高いサーバー認証情報を生成するのに安全です。
インターセプトとスクリプト
トラフィックをただ眺めるのをやめ、操作し始めたときからが本当の楽しみの始まりです。
1. ライブインターセプト
コンソールでiキーを押すと、インターセプトフィルタを設定できます。特定のログインエンドポイントに向かうすべてのリクエストを一時停止したい場合は、次のように入力します。
# フィルタを設定:
~u /v1/auth/login
リクエストはオレンジ色になり、転送中に一時停止します。その後、eを押してJSONボディを編集し(例えば、user_roleを「guest」から「admin」に変更するなど)、aを押して再開できます。これは、APIとWebセキュリティの脆弱性を特定し、バックエンドが悪意のあるデータをどのように処理するかをテストする上で、画期的な方法です。
2. Pythonによる自動化
手動での編集は時間がかかります。すべてのレスポンスに特定のヘッダーを注入する必要がある場合は、簡単なスクリプトを書きましょう。以下は、セキュリティヘッダーをシミュレートしたり、サーバーのレスポンスを動的に変更したりするために私が使用している10行のコードスニペットです。
from mitmproxy import http
def response(flow: http.HTTPFlow) -> None:
# 追跡用のカスタムヘッダーを注入
flow.response.headers["X-Audit-ID"] = "12345-DEBUG"
# テキストを置換してUIの変更をシミュレート
if "Welcome" in flow.response.get_text():
flow.response.set_text(flow.response.get_text().replace("Welcome", "ようこそ(アクセス許可)"))
mitmproxy -s modify_traffic.pyで実行します。
3. 必須のフィルタショートカット
ノイズに埋もれないようにしましょう。より高度なネットワーク可視化が必要な場面もありますが、膨大なデータの中から目的のものを見つけるには、以下のフィルタを使用します。
~m post: POSTリクエストのみを表示。~c 500: 厄介な内部サーバーエラー(500)を即座に特定。~b "token": リクエスト/レスポンスのボディから、JWTやAPIキーなどの特定の文字列をスキャン。!(~u analytics): GoogleやMixpanelなどのトラッキングノイズをすべて非表示。
現場からの実践的な教訓
私はセキュリティインシデント調査や監査で何百時間もmitmproxyを使用してきました。苦労して学んだ教訓をいくつか紹介します。
SSLピンニングの回避: 銀行やSNSなどの高セキュリティアプリは、SSLピンニングを使用しています。これらはシステムの信頼ストアを無視します。ログに「Client Handshake Failed」と表示される場合は、mitmproxyでトラフィックを確認する前に、FridaやObjectionを使用してアプリ内のピンニングロジックを無効にする必要があります。
メモリ管理: mitmproxyはすべての「フロー」をRAMに保存します。大量のブラウジングをしながら一日中実行し続けると、メモリ使用量が簡単に1GBに達することがあります。定期的にzキーを押してバッファをクリアし、インターフェースのレスポンスを維持しましょう。
クリーンアップ: プロキシのCA証明書をメインのマシンに必要以上に長くインストールしたままにしないでください。これは重大なセキュリティリスクになります。個人の銀行口座やメールの安全を守るため、テストセッションには専用の「汚染用」ブラウザプロファイルや仮想マシンを使用することをお勧めします。
コラボレーション: バグを見つけましたか?Wキーを使用して、特定のフローをファイルに保存します。そのファイルをSlackでチームメイトに送信すれば、彼らはmitmproxy -r bug_report.flowで読み込んで、あなたが見つけた正確なヘッダー、タイミング、ペイロードを確認できます。
mitmproxyは、HTTPSという「ブラックボックス」を、明確で編集可能なストリームに変えてくれます。デバッグの方法を一変させ、闇雲な推測からデータに基づいた修正へと導いてくれるでしょう。

