この記事は、Akatsuki Advent Calendar 2021の24日目の記事です。
こんにちは、セキュリティエンジニアの小竹 泰一(aka tkmru)です。 アカツキでは、アプリケーションに対する脆弱性診断や社内ネットワークに対するペネトレーションテスト、ツール開発/検証を担当しています。
Apple Silicon MacをiOSアプリの脆弱性診断に使用する際にどのような利点、欠点があるのか調査した結果を書きたいと思います。2019年のAkatsuki Advent Calendarから続く、大好評企画(?)「ペンテスターは〇〇に夢を見るか」シリーズ第二弾です。 第一弾はこちら。
Apple Silicon MacでiOSアプリが動作するように!
M1搭載MacBookが登場して、iOSアプリがエミュレータを使わずともmacOS上で動作するようになりました。
iPhoneおよびiPad向けAppが、Appleシリコン搭載のMac上のMac App Storeでも提供されるようになりました。AppをMac向けに修正する必要はなく、ユーザーとデベロッパの双方にとって新たな可能性が広がります。iPhoneおよびiPad向けAppで利用可能な既存の機能を使って、キーボード、ウインドウ、タッチ入力のジェスチャと連携して動作するようAppを最適化することができます。さらに既存の機能を確認し、必要に応じて機能を有効化/無効化することで、AppのMac上での動作を調整することも可能です。
JailbreakしていないiPhoneはAndroidと比べ、プラットフォーム側の制限が厳しく、かゆいところに手が届かないがちです。 そこでApple Silicon Macを使うことでiOSアプリの脆弱性診断が簡単になるのではと考え、検証しました。 この記事はその検証結果をまとめたものです。
iOSアプリのインストール方法
IPAファイルをダブルクリックすることでインストールできます。 Apple Silicon Mac上では、IPAファイルはインストーラとして振る舞います。 どんなIPAファイルでもインストールできるわけではなく、iOSデバイスと同等の制限があり、macOSのUUIDを実行許可している証明書でリザインされたものしかインストールできません。
tap1000000.appは検証用に作成したアプリの名前です。この記事内では度々tap1000000.appが登場します。
各種Tips
検証する過程で分かった各種Tipsを紹介します。 デスクトップアプリと同じようにiOSアプリを扱えました。
アクティビティモニタが便利
macOSにデフォルトでインストールされているアクティビティモニタを開き、実行しているプロセスを選択することで、プロセスの詳細な情報を取得できます。 PIDや使用しているファイルを確認できます。
これはiOSアプリのためのTipsではなく、macOS上で動作する全てのアプリケーションで使えるテクニックです。
メモリマップの取得方法
vmmapコマンドでPIDで指定したプロセスのメモリマップを取得できます。
$ vmmap 10299 Process: tap1000000 [10299] Path: /Volumes/VOLUME/*/tap1000000.app/tap1000000 Load Address: 0x1025e8000 Identifier: jp.hoge.tap1000000 Version: 0.1 (0) Code Type: ARM64 Platform: iOS Parent Process: ??? [1] ... ==== Non-writable regions for process 10299 REGION TYPE START - END [ VSIZE RSDNT DIRTY SWAP] PRT/MAX SHRMOD PURGE REGION DETAIL __TEXT 1025e8000-1025f0000 [ 32K 16K 0K 0K] r-x/r-x SM=COW /var/folders/*/tap1000000.app/tap1000000 __LINKEDIT 1025f4000-1025fc000 [ 32K 0K 0K 0K] r--/r-- SM=COW /var/folders/*/tap1000000.app/tap1000000 VM_ALLOCATE 102604000-102608000 [ 16K 16K 16K 0K] r--/rwx SM=PRV shared memory 102608000-10260c000 [ 16K 16K 16K 0K] r--/r-- SM=SHM MALLOC metadata 10260c000-102610000 [ 16K 16K 16K 0K] r--/rwx SM=COW MallocHelperZone_0x10260c000 zone structure MALLOC guard page 102614000-102618000 [ 16K 0K 0K 0K] ---/rwx SM=ZER MALLOC guard page 102620000-102624000 [ 16K 0K 0K 0K] ---/rwx SM=ZER MALLOC guard page 102624000-102628000 [ 16K 0K 0K 0K] ---/rwx SM=NUL MALLOC guard page 102630000-102638000 [ 32K 0K 0K 0K] ---/rwx SM=NUL ...
これもiOSアプリのためのTipsではなく、macOS上で動作する全てのアプリケーションで使えるテクニックです。
中間者攻撃の方法
システム環境設定からネットワーク
-> 詳細設定
を開き、使用しているネットワークを選択した後、 詳細
-> プロキシ
の順にメニューを開くことでプロキシの設定画面を開けます。
HTTP/HTTPS通信を取得するには構成するプロトコルにWebプロキシ(HTTP)
、保護されたWebプロキシ(HTTPS)
を選択し、プロキシツールが動いているアドレス/ポートを指定してください。
ただ、PCから出る全ての通信が指定したプロキシツールを通るようになるので、プロキシツール側でうまくフィルタしてあげる必要があります。 この辺りもiPhoneの場合と変わりませんが、PC上では診断対象のアプリと並行してブラウザなども動かすと思うのでフィルタリングがより大切になります。
各種パス
インストールされたアプリは次のパスに配置されます。
/Applications/tap1000000.app/Wrapper/tap1000000.app
また、用途は特定できていませんが、アプリの実行中は次のパスにもアプリが配置されます。
/private/var/folders/hc/XXXXXXXXnsfn1_c9n20jxw40000gq/X/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/d/Wrapper/tap1000000.app
アプリが使用するアプリケーションコンテナは次のパスに配置されます。
/Users/taichi.kotake/Library/Containers/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/Data/
このあたりのパスは前述のアクティビティモニタから確認できるので、興味がある方は見てみてください。
欠点
現状、Apple Silicon Mac上でWindows VMを動かせないのは欠点です。 ゲームアプリの脆弱性診断では、Unity製アプリのバイナリのシンボルを復元するIl2CppDumperというツールを動かすためにWindows VMをしばしば使います。
まず、VMware FusionがApple Silicon Mac上では動作しません。 VMware FusionのApple Silicon Mac対応は進んでいるようですが、Intel版のOSをサポートはしないようで、Apple Silicon Mac対応VMware Fusionがリリースされたとしても、Intel版Windowsは実行できない見込みです。 Microsoftは仮想環境向けにARM版Windowsを販売しないようで、当分はApple Silicon Mac上でWindows VMを動かせなさそうです。
内製メモリ改ざんツールをApple Silicon Macに対応させた話
アカツキのセキュリティチームでは脆弱性診断のためのツールをいくつか内製し、OSSとして公開しています。 その中の一つにipa-meditというiOSアプリ向けのメモリ改ざんツールがあります。 このツールをApple Silicon Mac上で動作するiOSアプリに対応させました。ここでは、その解説をしたいと思います。
Apple Silicon Macに対応する以前のバージョンのipa-meditは以前、Black Hat USA 2021 Arsenalで発表しました。 この記事はApple Silicon Macの解説のための記事なので、iPhone、iPad上で動作するiOSアプリに対してメモリ改ざんするロジックの解説はここではしません。興味がある方は次のスライドをご覧ください。
メモリ改ざんとは
チートの方法の1つにUI上に表示されている値を端末のメモリ上から検索し、見つけた値を改ざんする、「メモリ改ざん」という手法があります。 これはゲームへのチート方法の中で最も簡単な方法で、脆弱性診断の際には実際にメモリ上のデータを改ざんをすることでチートできるかどうか確認しています。 対策としては、XOR等を使ってメモリ上ではエンコードされた状態で値を保持し、UI上に表示されている値を検索されても見つからないようにする方法があります。 ipa-meditでは次のようにメモリ改ざんを行えます。
LinuxとmacOSの違いに困惑...
要はmacOS上で動作するアプリケーションをデバッグすればいいだけなので、シュッと対応できるのではと開発時には考えていました。 しかし、慣れ親しんでいたLinux環境でのシステムプログラミングとは違い、macOS固有の知識が要求されるため、いくつか戸惑うことがありました。
Linuxとの違いに戸惑う....
apk-meditというAndroid向けのメモリ改ざんツールを以前作成したことがあったので、このツールと同じロジックで作れるのではないかと考えていましたが、かなり勝手が違いました。 LLDBやGolang製デバッガのDelveなどのmacOSでも動作するデバッガのコードが実装の参考になりました。
/proc がない....
Linux系OSの場合は/proc/$pid/maps
から、特定のプロセスのメモリマップを取得し、/proc/$pid/mem
よりメモリを読み書きできます。
しかし、macOSには/proc
がありません。
そのため、専用のAPIを用いて、メモリマップの取得とメモリの読み書きを行う必要があります。
ipa-meditではメモリマップの取得には前述のvmmapコマンドを使っていますが、
メモリの読み込みにはmach_vm_read
を、メモリへの書き込みにはmach_vm_write
を使っています。
ptraceでメモリの読み書きができない....
ptraceは、デバッガを実装する際によく用いられるシステムコールで、第一引数にrequestという動作モードを表す定数を指定することで動作を切り替えられます。 Linux系OSの場合はptraceを使ってプロセスへアタッチし、プロセスを停止させたり、メモリを読み書きできます。
ptrace(int request, pid_t pid, caddr_t addr, int data);
しかし、macOSの場合はメモリの読み書きがサポートされておらず、第一引数にメモリを読むためのPTRACE_PEEKDATA、メモリへ書き込むためのPTRACE_POKEDATAを指定できません。そのため、前述のmach_vm_read
、mach_vm_write
を使ってメモリの読み書きを行っています。
macOSでもアタッチ/デタッチにはptraceを使えるので、ipa-meditではアタッチ/デタッチにのみptraceを使っています。
署名まわりで戸惑う....
macOSでは、署名されていないプログラムをデバッガとして使うことはできません。
デバッガとして使うプログラムには、com.apple.security.cs.debuggerという属性を有効にするようentitlements.plist
で指定し、署名しておく必要があります。
ipa-meditではmake build
コマンドでビルドする際に署名の処理も行っています。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.cs.debugger</key> <true/> </dict> </plist>
また、デバッグ対象のアプリではcom.apple.security.get-task-allow
属性を有効にしておく必要があります。
この属性はデバッガによるアタッチを許可します。
Apple Silicon Macを使ってiOSアプリの脆弱性診断をする際には、リザインの際にこの属性を有効にしておかないとメモリ改ざんを行えません。
デバック対象のアプリでcom.apple.security.get-task-allow
属性が有効になっているかどうかはcodesignコマンドで確認できます。
$ codesign -d --entitlements :- 47071 Executable=/private/var/folders/hc/XXXXXXXXnsfn1_c9n20jxw40000gq/X/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/d/Wrapper/tap1000000.app/tap1000000 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>application-identifier</key> <string>XXXXXXXXXX.jp.hoge.tap1000000</string> <key>com.apple.developer.team-identifier</key> <string>XXXXXXXXXX</string> <key>get-task-allow</key> <true/> <-- ここがtrueになっている必要がある <key>keychain-access-groups</key> <array> <string>XXXXXXXXXX.jp.hoge.tap1000000</string> </array> </dict> </plist>
まとめ
検証の結果、Apple Silicon Mac上で動作するiOSアプリに対しても問題なく脆弱性診断ができそうだと分かりました。 Apple Silicon Mac上のiOSアプリに対して脆弱性診断っぽいことを行うまとまったドキュメントは、インターネット上にまだなく(多分)、MITMする方法すら検索しても出てこないので、公開する意義のあるいいドキュメントになったかなと思います。
また、PC上で動作しているため、アプリケーションコンテナ内のファイルへの操作をXcodeを介さず行える点や、デバッガのアタッチをデスクトップアプリと同じ方法で行える点から、一部の診断は実機のiPhoneを使うよりやりやすくなる印象を受けました。 iPhoneをJailBreakしなくとも、ターミナルが動作している環境でiOSアプリを動かせるのは便利かなーと思います。 今後、Apple Silicon Mac環境特有の何かを用いたiOSアプリへのハック方法が出てくると面白いなと思います。
関連情報
Apple Silicon Macには、Intel Mac向けにビルドされたアプリケーションをApple Silicon Mac上で動作させるRosetta 2という仕組みが搭載されています。 この動作を明らかにするProject ChampollionというリサーチをFFRIが行っており面白いです。 iOSアプリとは関係ないですが、Apple Silicon Mac特有の仕組みに興味がある方はこちらもおすすめです。