HTTPS通信でもデータ漏洩|iOS・MacOSでのmitmproxy中間者攻撃対策
iOSとMacOSユーザー向けに、mitmproxyによる中間者攻撃でAPI通信が盗聴される問題を解説。HTTPS利用時の盲点を明確化し、効果的な防御策でデータ保護を強化します。
本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。
記事一覧
APPはHTTPSで通信しているが、データは盗まれてしまった。
iOS+MacOSでmitmproxyを使った中間者攻撃(Man-in-the-middle attack)によるAPI通信データのスニッフィング方法と防御策の解説
前書き
先日、会社で内部のCTF競技会を開催しました。問題を考えているとき、大学時代にPHPでバックエンドを担当していたプロジェクトを思い出しました。ポイントを集めるアプリで、タスクリストがあり、条件を達成するとAPIを呼び出してポイントを獲得する仕組みです。社長は「APIはHTTPSで暗号化されているから安全だ」と考えていましたが、私が中間者攻撃を見せて、通信データを盗聴し、API呼び出しを偽造してポイントを不正に取得できることを証明しました…。
さらに近年のビッグデータの台頭により、ウェブクローラーがあふれています。クローラーと防御の戦いは激化し、クローリングと防御の間でさまざまな手法が繰り広げられています。まさに「技術が一歩進めば、それを上回る技術が現れる」という状況です!
スクレイピングのもう一つのターゲットはAPPのAPIです。防御がなければほぼ門戸が開きっぱなしの状態です。操作が簡単でフォーマットも整っており、検出やブロックされにくいです。もしウェブ側であらゆる対策をしてもデータが繰り返しスクレイピングされるなら、APPのAPIに脆弱性がないか確認してみましょう。
このテーマはCTF大会でどう出題すればいいかわからなかったので、記録として記事を単独でまとめました。本稿はあくまで概念の概要です — HTTPSは証明書の差し替えで通信内容を復号できる、および安全性を強化する方法について。実際のネットワーク理論は得意ではなく先生にお任せしているので、この分野の知識がある方は時間をかけずに読み飛ばしても構いません。もしくは記事の最後までスクロールしてAPPの保護方法を確認してください!
実際の操作
環境: MacOS + iOS
Androidユーザーは直接Packet Capture(無料)をダウンロードできます。iOSユーザーはSurge 4(有料)を使用してMITM機能をアンロックできます。MacOSでは別の有料ソフトCharlesも利用可能です。
本記事はiOSで無料のmitmproxyを使った操作方法を解説しています。もし上記の環境があれば、わざわざ面倒なことをせずに、直接アプリを開いてスマホでVPNを設定し、証明書を差し替えるだけで中間者攻撃が可能です!(同様に、保護方法は記事の最後までスクロールしてご覧ください!)
[2021/02/25 更新]: Macには新しい無料のグラフィカルインターフェースプログラム(Proxyman)が利用可能で、こちらの記事の第一部と組み合わせて使えます。
インストール mitmproxy
brew を使った直接インストール :
1
brew install mitmproxy
インストール完了!
p.s brew: command not found が表示された場合は、まず brew パッケージ管理ツールをインストールしてください :
1
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
mitmproxy の使用方法
インストール完了後、Terminalで以下のコマンドを入力して起動します:
1
mitmproxy
起動成功
スマホとMacを同じローカルネットワークに接続し、MacのIPアドレスを取得する
方法(1) MacがWiFiに接続、スマホも同じWiFiを使用
MacのIPアドレス = 「システム環境設定」->「ネットワーク」->「Wi-Fi」->「IPアドレス」
方法(2) Macで有線ネットワークを使用し、インターネット共有を有効にする;スマホをそのホットスポットに接続する:
「システム環境設定」->「共有」->「Ethernet」を選択->「Wi-Fi」にチェック->「インターネット共有」を有効にする
MacのIPアドレス = 192.168.2.1 (️️注意⚠️ イーサネットのIPではなく、Macがネットワーク共有のアクセスポイントとして使うIPです)
携帯ネットワーク設定WiFi — プロキシサーバー情報
「設定」-> 「WiFi」-> 「HTTPプロキシ」-> 「手動」-> 「サーバーにMacのIPアドレスを入力」-> 「ポートに8080を入力」-> 「保存」
この時点でウェブページが開けず、証明書エラーが出るのは正常です;続けて進めましょう…
mitmproxy のカスタム HTTPS 証明書のインストール
上述のように、中間者攻撃の実現方法は通信中に自分の証明書を使ってデータの暗号化・復号を差し替えることです。したがって、スマートフォンにもこのカスタム証明書をインストールする必要があります。
1.スマホのSafariで http://mitm.it を開く
左側に「->Proxy設定✅」が表示される場合、Proxy設定は正しいことを示します。
右側に表示される場合は、Proxy設定に誤りがあることを示します🚫
「Apple」->「プロファイルをインストール」->「インストール」
⚠️ここで終わりではありません。次にプロファイルの有効化について説明します
「一般」->「設定」->「証明書の信頼設定」->「mitmproxy」を有効にする
完了!これでブラウザに戻ると正常にウェブページを閲覧できます。
Macに戻ってmitmproxyを操作する
mitmproxyのターミナル上で、先ほどのスマホのデータ通信記録を確認できます。
嗅ぎたい記録を見つけて、Request(送信されたパラメータ)とResponse(返された内容)を確認する
よく使う操作キーセット:
1
2
3
4
5
6
7
8
9
10
11
12
13
「 ? 」= キー操作一覧を表示
「 k 」/「⬆」= 上へ
「 j 」/「⬇」= 下へ
「 h 」/「⬅」= 左へ
「 l 」/「➡️」= 右へ
「 space 」= 次のページ
「 enter 」= 詳細表示へ移動
「 q 」= 前のページに戻る/終了
「 b 」= レスポンスボディを指定パスのテキストファイルにエクスポート
「 f 」= 記録のフィルタ条件
「 z 」= すべての記録をクリア
「 e 」= リクエスト編集(cookie、headers、params...)
「 r 」= リクエストを再送信
CLIに慣れていない?大丈夫、Web GUIに切り替えられます!
mitmproxy の起動方法以外に、以下のように変更できます:
1
mitmweb
新しい Web GUI を使って操作や観察ができます
mitmweb
メインイベント、APPデータのスニッフィング:
上述の環境がすべて整い、操作に慣れたら、いよいよ本題に入ります;APPのAPIデータ通信内容を嗅ぎ取る!
ここでは、ある不動産アプリを例にしており、悪意なく純粋に学術交流のために使用しています!
私たちはオブジェクトリストのAPIがどのようにリクエストされ、どんな内容が返されるのか知りたいです!
まず「z」を押してすべての記録をクリアします(混乱を避けるため)
ターゲットアプリを起動する
ターゲットのAPPを開き、「プルダウンリフレッシュ」や「次のページを読み込む」動作を試してください。
🛑もしターゲットのAPPが起動しない、接続できない場合;申し訳ありませんが、そのAPPは防御されており、この方法での解析はできません。直接「どうやって保護するか」の章へスクロールしてください🛑
mitmproxy ログ
mitmproxyに戻り、記録を確認して、探偵の精神でどのAPIリクエスト記録が目的のものか推測し、詳細を確認しましょう!
リクエスト
Request 部分では、どのパラメータが送信されたかを見ることができます。
「e」で編集し、「r」で再送信して、レスポンスを観察することで各パラメータの用途を推測できます!
レスポンス
Response も直接に生の返却内容を取得できます。
🛑もしResponseの内容が大量にエンコードされている場合、申し訳ありませんが、APPが独自に再度暗号化・復号化を行っている可能性があり、この方法では解析できません。直接「如何に保護するか」の章までスクロールしてください🛑
読みづらい?中国語が文字化けしている?問題ありません。ここで「b」を使ってテキストファイルをデスクトップにエクスポートし、内容を Json Editor Online にコピーして解析してください!
**または直接 mitmweb を使って Web GUI から直接閲覧・操作*
mitmweb
嗅探、観察、フィルタリング、テストを行うことで、APPのAPIの動作方法がわかり、それを利用してクローラーでデータを取得できます。
必要な情報を収集し終えたら、必ずmitmproxyを停止し、スマホのネットワークプロキシ設定を自動に戻してから正常にネットワークを使用してください。
APPはどうやって自己防衛すべきか?
mitmproxyを使用した後にAPPが動作せず、返される内容がエンコードされている場合、APPが保護を行っていることを意味します。
方法(1):
大まかには証明書情報をAPP内に入れておき、現在のHTTPSで使われている証明書がAPP内の情報と一致しなければアクセスを拒否します。詳しくはこちらやSSL Pinningの関連資料をご覧ください。欠点は証明書の有効期限に注意が必要なことです。
https://medium.com/@dzungnguyen.hcm/ios-ssl-pinning-bffd2ee9efc
方法(2):
APP側はデータを送信する前にまずエンコードと暗号化を行い、APIのバックエンドは受信後に復号して元のリクエスト内容を取得します。APIの返却内容も同様にエンコードと暗号化を行い、APP側は受信後に復号して返却内容を取得します。手順は煩雑でパフォーマンスも消費しますが、確かに有効な方法です。私の知る限り、あるデジタル銀行がこの方法で保護を行っています。
しかし…
作法1、依然破解方法があります:iOS 12でSSL Pinningを回避する方法
方法2、リバースエンジニアリングを通じて暗号化に使われる鍵を取得することも可能です
⚠️100%の安全はありません⚠️
または穴を掘って這わせて、さまざまな証拠を収集し、法務で解決する(?
やはりこの言葉:
「クライアントを決して信頼しない」
mitmproxy のさらなる活用方法:
1. mitmdumpの使用方法
mitmproxy 、 mitmweb 、および mitmdump は、すべての記録を直接テキストファイルにエクスポートできます。
1
mitmdump -w /log.txt
そして、玩法(2) のPythonプログラムを使って、設定やトラフィックのフィルタリングが可能です:
1
mitmdump -ns examples/filter.py -r /log.txt -w /result.txt
2.pythonプログラムを使ったリクエストパラメータ設定、アクセス制御、リダイレクト:
1
2
3
4
5
6
7
8
9
10
11
12
from mitmproxy import http
def request(flow: http.HTTPFlow) -> None:
# pretty_hostはリクエストの"Host"ヘッダーを考慮します。
# これは通常IPしかない透過モードで便利です。
# リクエストパラメータ設定の例:
flow.request.headers['User-Agent'] = 'MitmProxy'
if flow.request.pretty_host == "123.com.tw":
flow.request.host = "456.com.tw"
# 123.com.twへのアクセスをすべて456.com.twにリダイレクトします
転送の例
mitmproxyを起動する際に以下のパラメータを追加します:
1
2
3
4
5
mitmproxy -s /redirect.py
or
mitmweb -s /redirect.py
or
mitmdump -s /redirect.py
穴埋め補足
mitmproxy を使用して HTTP 1.1 および Accept-Ranges: bytes、Content-Range の長い接続で断片的にリソースを継続取得するリクエストを観察する場合、レスポンスがすべて返ってくるまで表示されず、分割表示や持続接続による継続ダウンロードは行われません。
踏み台はこちら 。
さらに読む
あとがき
私はドメイン権限がないためSSL証明書情報を取得できず、実装もできませんでした。コードを見る限り難しくはなさそうです。100%安全な方法はありませんが、一つ防御を増やすだけでも多少は安全になります。さらに攻撃を続けるには多くの時間をかけて研究する必要があり、おそらく90%のスクレイパーは諦めるでしょう!
この記事は少し内容が薄いかもしれません。mediumはしばらく放置して(一眼レフで遊んでいました)、主に今週末(2019/09/21–2019/09/22)のiPlayground 2019に向けてリハビリ的に書いています。今年のプログラムが楽しみで🤩、戻ってからもっと良質な記事をたくさん書ければと思っています!
[2019/02/22 更新記事] iPlayground 2019 はどんな体験?
ご質問やご意見がありましたら、こちらからご連絡ください 。
Post は ZMediumToMarkdown によって Medium から変換されました。
本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。
















