mobile-audit について
mobile-auditは、OWASP MASVSとMASTGに沿ってiOS・Androidアプリを審査するセキュリティレビュー用スキルです。ソースコード、コンパイル済みバイナリ、実行時の挙動を調べ、許可されたテストと証拠に基づく記録を重視します。
主な機能
- 01MASVSに沿ったモバイルセキュリティ確認
- 02ストレージ、暗号、通信、認証の審査
- 03静的解析と実行時テスト
- 04証拠の検証と監査結果の記録
活用シーン
- 01アプリ内の機密データ保存を審査
- 02モバイルの通信・認証制御をテスト
- 03端末や他アプリとの連携リスクを調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ briiirussell/ cybersecurity-skills --skill mobile-auditインストール後、Claude Code で/mobile-auditを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/findings-format.mdfindings.schema.jsonseverity-calibration.mdto-sarif.mjsvalidate-findings.mjsverification.md詳細
モバイル監査 — iOS・Android アプリケーションのセキュリティレビュー
OWASP Mobile Application Security Verification Standard(MASVS)および Mobile Application Security Testing Guide(MASTG)に照らしてモバイルアプリを監査します。ソースコードレビュー、コンパイル済みバイナリの静的解析、実行時テストを対象とします。
対象範囲:このスキルでは、アプリとデバイス、バックエンド、その他のアプリとのやり取りを対象とします。バックエンド API のセキュリティについては、api-audit と併用してください。依存関係の CVE(CocoaPods、SPM、Gradle)については、dependency-audit と併用してください。
認可の確認
バイナリのリバースエンジニアリングや実行時テストを行う前に、次の点を確認してください。
- アプリが自分のものであるか、パブリッシャーから書面による許可を得ていること
- 自分が管理する環境(テストデバイス、エミュレーター、専用のサンドボックス)で作業していること
- アプリストアの利用規約 — Apple と Google は一般に、自分が所有するアプリのセキュリティ調査を認めています。許可なく競合他社のアプリをテストすると、法的リスクにさらされる可能性が高まります
不明な点がある場合は、作業を始める前に確認してください。
監査チェックリスト — MASVS-STORAGE(機密データの保存)
- iOS: キーチェーン項目では、利用可能な中で最も強い
kSecAttrAccessibleクラス(kSecAttrAccessibleWhenUnlockedThisDeviceOnlyまたはkSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)を使用します。AlwaysとThisDeviceOnlyを含まないバリアントは避けてください - iOS:
NSUserDefaults、plist、アプリバンドルにシークレットがないこと —strings <app>.ipaで API キーやシークレットが見つからないことを確認します - Android: シークレットは生の SharedPreferences ではなく、EncryptedSharedPreferences または Keystore による暗号化ストレージに保存します
- Android: マニフェストで
android:allowBackup="false"を指定します(またはバックアップルールを慎重に設定します)。そうしないと、adb backupですべてのデータが抽出されます - 両方: クラッシュ後も残るログ(NSLog、Log.d、サードパーティ製クラッシュレポーター)に PII やトークンを書き込まないこと
- 両方: ペーストボード/クリップボードへのアクセス — 機密情報を含むフィールドがシステムのクリップボードに自動共有されないこと(iOS の
pasteboard.expirationDate、Android のClipDescription.EXTRA_IS_SENSITIVE) - 両方: OS のアプリスイッチャーのスクリーンショットに機密画面が写らないこと — iOS では
applicationDidEnterBackgroundでぼかし、Android ではアクティビティにFLAG_SECUREを設定します
監査チェックリスト — MASVS-CRYPTO(暗号化)
- アプリバンドルにハードコードされたキーがないこと —
strings、class-dump、apktoolで埋め込み定数が見つからないことを確認します - 最新のアルゴリズムのみを使用します — AES-GCM、ChaCha20-Poly1305。AES-ECB、DES、RC4、MD5、SHA-1 は拒否します
- 乱数生成には
SecRandomCopyBytes(iOS)/SecureRandom(Android)を使用します。暗号化にarc4random()を使わず、Math.random()は絶対に使わないでください - パスワードからの鍵導出には、PBKDF2 を 600,000 回以上反復する設定(OWASP 2024)、または Argon2id を使用します
- IV/ノンスを再利用しないこと —
iv = "0000000000000000"が見つかった場合、平文のパターンが明らかになるため、暗号化しないよりも危険です - 独自の暗号化を実装しないでください — カスタム暗号化方式はすべて指摘し、libsodium/Tink を優先してください
監査チェックリスト — MASVS-NETWORK(ネットワーク通信)
- iOS: App Transport Security が有効であること — グローバルな
NSAllowsArbitraryLoads = trueを設定しないでください。例外がある場合は、対象ドメインを限定し、正当な理由を示して文書化します - Android:
network_security_config.xmlが存在し、平文通信の拒否を強制していること —<base-config cleartextTrafficPermitted="false"> - 両方: 高い信頼性が求められるバックエンドには証明書ピンニングを設定します — 証明書のローテーションに耐えられる公開鍵ピンニングを、証明書ピンニングより優先します。iOS では
URLSessionDelegateとURLAuthenticationChallenge、Android ではNetworkSecurityConfigの<pin-set>または OkHttp のCertificatePinnerを使用します - 両方: ピンニングにはバックアップピンを用意します — 証明書を 1 つだけピン留めすると、次のローテーション時にすべてのユーザーのアプリが動作しなくなります
- WebView の使用 — iOS では
UIWebViewではなくWKWebViewのみを使用します。JavaScript ブリッジを監査し、WebView で JavaScript が不要な場合はsetJavaScriptEnabled(false)を設定します - WebView の
loadUrlにユーザーが制御する URL を渡す場合 — オープンリダイレクト、インテント偽装、フィッシングのリスクがあります
監査チェックリスト — MASVS-AUTH(認証とセッション)
- 生体認証プロンプトには、非推奨の
FingerprintManagerではなく、LAContext.evaluatePolicy(iOS)/BiometricPrompt(Android)を使用します - 生体認証は、単なる UI チェックではなく、キーチェーン/キーストアへのアクセスに紐付けます(
SecAccessControl.biometryAny、Android のKeyGenParameterSpec.setUserAuthenticationRequired(true)) - セッショントークンはキーチェーン/キーストアに保存します(SharedPreferences/NSUserDefaults には保存しません)
- リフレッシュトークンのフローを使用します。アクセストークンの有効期間を短くし、リフレッシュトークンはサーバー側で失効できるようにします
- OAuth フローではプラットフォームのブラウザーを使用します(iOS では ASWebAuthenticationSession、Android では Custom Tabs)。WebView は決して使用しません(認証情報が簡単に盗まれます)
- アプリが機密データを保持する場合、アプリレベルのパスコードをデバイスのロック解除とは独立させます
監査チェックリスト — MASVS-PLATFORM(プラットフォームとの連携)
ディープリンク/URL スキーム(iOS)とインテントフィルター(Android)
- すべてのエクスポートされたアクティビティ(
android:exported="true")について、パラメーターの処理を確認します - ユニバーサルリンク(iOS)とアプリリンク(Android)では、カスタムスキーム(
myapp://)ではなく、HTTPS と検証済みドメインを使用します(カスタムスキームはどのアプリでも登録できます) - 購入、共有、アカウント変更などの機密性の高い操作を実行するディープリンクでは、アプリ内でユーザーの確認を求めます
- WebView で読み込む URL をフィルタリングします。ユーザーの同意なしに、WebView から
myapp://を開いてアプリ内操作を実行させることは、XSS から操作を実行させる攻撃チェーンになります
プロセス間通信(Android)
- コンテンツプロバイダーは、アプリ間アクセスを明示的に意図していない限り、
android:exported="false"にします。エクスポートする場合は、すべての URI パスを検証します - サービスでは、エクスポートされたサービスに権限文字列を設定します。
android:permissionなしで公開すると、どのアプリからでも呼び出せます - ブロードキャストレシーバーでは、アプリ内ブロードキャストに
LocalBroadcastManagerを使用し、システムブロードキャストを検証します
プロセス間通信(iOS)
- アプリグループは、共有が本当に必要な場合にのみ設定します
- キーチェーンアクセスグループは自社アプリのみに制限し、無関係なバンドルとキーチェーングループを共有しません
- URL スキームハンドラーでは、送信元アプリを検証します(
UIApplication.openURLのオプションにはUIApplicationOpenURLOptionsSourceApplicationKeyが含まれます)
監査チェックリスト — MASVS-CODE(コード品質)
- ネイティブライブラリでは最新のコンパイラーを使用し、スタックカナリアを無効にせず、PIE を有効にします(iOS では
otool -hv、Android の.soではreadelf -h) - リリースビルドではシンボルを削除します(
strip、ProGuard/R8) - 本番環境にデバッグビルドを含めません(
DEBUGフラグ、マニフェストのisDebuggable) - リフレクションを使用する非公開 API(Android の非 SDK インターフェース)は使用しません。OS のアップグレードで動作しなくなります
- アップデート:既知の脆弱性があるバージョンを使い続けられないよう、アップグレードを強制するアプリ内アップデートプロンプトを表示します
監査チェックリスト — MASVS-RESILIENCE(リバースエンジニアリング対策)
このカテゴリは MASVS では任意と評価されています。必要なのは、リスクの高いアプリ(銀行、DRM、政府機関向け)のみです。ほとんどのアプリでは、ここに労力をかける必要はありません。安全な暗号と適切なバックエンドを用意してください。
必要な場合:
- ジェイルブレイク/ルート検出は完全ではありません(検出手法はどれも公開された回避方法があります)が、攻撃コストを引き上げます
- コード難読化:価値の高いアプリには DexGuard/Arxan、すべてのアプリでは標準の ProGuard/R8 を最低限使用します
- デバッグ対策:
ptraceによる自己アタッチ(iOS/Linux)、Debug.isDebuggerConnected(Android) - Frida のような回避手法に耐性のある SSL ピンニングを実装します。Swift/Kotlin ではなく、ネイティブコードでピンを設定します
注:物理的にデバイスへアクセスできる、強い意志を持った攻撃者は、あらゆる耐性対策を回避します。こうした対策は時間稼ぎにはなりますが、攻撃を防ぐものではありません。
静的解析ツール
| ツール | プラットフォーム | 用途 |
|---|---|---|
| MobSF | iOS + Android | 自動静的・動的スキャナー。初期トリアージに使用 |
| nuclei + mobile templates | 両方 | パターンベースのスキャナー |
| semgrep + mobile rules | 両方 | AST ベースのルール |
| jadx | Android | APK を Java に逆コンパイル |
| apktool | Android | APK を逆アセンブル |
| Hopper / Ghidra / IDA | iOS | Mach-O を逆アセンブル |
| class-dump / nm / otool | iOS | シンボルと構造の調査 |
strings | 両方 | 最初の確認 — シークレット、URL、デバッグ文字列 |
| Frida + objection | 両方 | ランタイム計装、SSL ピンニングのバイパス、メソッドのトレース |
ランタイムテスト
グレーボックス/ブラックボックス評価では、個人情報のないデバイスを使用します。
- テストデバイスのシステムプロキシとして Burp Suite / mitmproxy を使用 — API トラフィックを観察します
- テスト中に暗号化されたトラフィックを確認する必要がある場合は、Frida +
objectionで SSL ピンニングをバイパスします - リクエストを変更して再送信し、IDOR / BFLA を探します(
api-auditを参照) - バックグラウンドへの移行後に再開し、セッション処理とスクリーンショットのぼかしをテストします
- 強制終了後に再起動し、セッションの永続性と自動ログインをテストします
- 悪意のある同一開発元のアプリをインストールし、IPC 経路をテストします(Android Intent ファジング)
検証してから記録する
各候補は findings.json に記録する前に、references/verification.md の反証パスを通します。引用された証拠から始めて主張を否定できるか試す、独立したレビューです。references/findings-format.md に従って、各候補の判定は必ず1つに確定します。影響が追跡されていないギャップは、記録ではなく強化に関する注記です。
逆コンパイルしたバイナリの引用。 モバイルの所見は通常、リポジトリの行番号を示せるソースではなく、コンパイル済みアプリから得られます。読み取り専用ツールの出力(strings、jadx / apktool による逆コンパイル結果、class-dump、otool -hv、readelf -h、マニフェストまたは plist のダンプ、プロキシ経由のリクエスト/レスポンス)を、機密情報を伏せて <audit dir>/evidence/<name>.txt(または .json)に保存し、location と各 evidence[] エントリにはそのファイルと該当行を指定します。シークレット値を証拠ファイルに記録しないでください。 ハードコードされたキーの証拠として示すのは、そのキーを使用する逆コンパイル済みの呼び出し箇所であり、種類と末尾4文字だけが分かるように伏せます。キーそのものは記録しません。
confirmed— 攻撃者が到達可能な入力(または抽出したアーティファクト)から影響までの完全なトレース、あるいはランタイムでの実証がある場合です。例:stringsで逆コンパイル済み APK から AES キーを読み取り、そのキーを使用する復号呼び出しまでトレースした(証拠ファイルを保存済み。静的解析のみのため、confidence: medium);テスト用プロキシで平文のログイン情報を取得した。これはInfo.plistにNSAllowsArbitraryLoads=trueが含まれているためであり、出荷時のデフォルト設定が寛容なので、これを上書きしないビルドに対するsystem_configuration条件を付けてconfidence: mediumでconfirmedとし、リクエストを取得できた時点でreproduced: trueとします。needs_validation— バイナリは主張を裏付けていますが、決定的な事実の1つがデバイスの外部にあり、確認できない場合です。例:実際のリスクが確認できないバックエンドの認可に依存するandroid:exported="true"のアクティビティ、または実行中のアプリがそのドメインに接続することをまだ確認していないnetwork_security_configの平文通信例外。説明しただけで実行していないライブチェック(プロキシでの取得、Frida フック)はconfirmedではなく、取得を検証計画として記載したneeds_validationです。rejected— 名前付きの場所にある明示された制御によって候補が否定される場合です。例:android:debuggable="false"のリリースマニフェストにおいて、if (BuildConfig.DEBUG)の背後にあるトークンのLog.d(ruled_out_byには証拠ダンプ内のマニフェスト行を指定);「ハードコードされたキー」の候補が、適切な制限が設定された公開可能な Firebase / Maps 識別子である場合(references/severity-calibration.md §6 を参照)。 重大度は、references/severity-calibration.md に従って調整したうえで、confirmedレコードにのみ設定します。overall ≤ demonstrated impactとし、静的解析のみで抽出した場合、確信度の上限はmediumです。トレースされた影響がない MASVS-RESILIENCE のギャップ(root/jailbreak 検出、難読化、アンチデバッグ)は、脆弱性ではなく強化に関する注記です。攻撃者のコストを上げるだけで、境界を越えるものではありません。
ドメイン固有のフィールドは ext(任意のレコードに設定できるオブジェクト)に記録します。
ext キー | 意味 | 例 |
|---|---|---|
masvs | MASVS コントロール ID | MASVS-STORAGE-1 |
platform | 指摘が該当するプラットフォーム | ios | android | both |
source | エビデンスの取得元 | source | decompiled | runtime |
フィンガープリント:mobile-audit/<masvs-or-class>/<file or resource>/<symbol or name>。スラッシュ区切りとし、行番号は含めません(バリデーターは :<digits> のセグメントを拒否します)。例:mobile-audit/MASVS-NETWORK-1/Info.plist/NSAllowsArbitraryLoads、mobile-audit/MASVS-STORAGE-1/AndroidManifest.xml/allowBackup、mobile-audit/MASVS-CRYPTO-2/com/acme/app/crypto/Vault/decrypt。逆コンパイルしたアプリでは、エビデンスのファイル名ではなく、コードが存在するクラスまたはシンボルを使用してください。こうすることで、エビデンスを再取得してもフィンガープリントが変わりません。
findings.json をフィンガープリント順に作成し、検証に合格するまで修正してください。
node references/validate-findings.mjs findings.json
必要に応じて SARIF にエクスポートできます:node references/to-sarif.mjs findings.json -o findings.sarif。処置(Fixed / Deferred / Accepted Risk / Mitigated (platform/config) / Requires major migration)は後から設定します。通常は finding-triage が担当します。誤検知は処置ではなく、rejected レコードとして記録します。
出力形式
まず findings.json を作成して検証してください。Markdown レポートは JSON から生成され、JSON に記載されていない判定や重大度が変更されることはありません。
# Mobile Application Security Audit
## App: [name + version] ## Platform: iOS / Android / both ## MASVS profile: L1 / L2 / R
## findings.json: [path] — validated: [yes] ## Date: [date]
### Summary
- Confirmed: [N] (Critical [n] | High [n] | Medium [n] | Low [n]) Needs validation: [N] Rejected: [N]
### Confirmed findings
#### [SEVERITY] [Title] `fingerprint`
**Location:** `evidence/<file>:line` (or repo `path:line`) **MASVS:** [MASVS-X-n] **CWE:** [CWE-n] **Platform:** [ios | android | both] **Confidence:** [medium | high (reproduced)]
**What and why it matters:** [the trace, in a few lines]
**Fix:** [concrete change] **Verify the fix:** [the check that proves it]
### Needs validation
| Finding | Blockers | Check for the owner to run |
|---|---|---|
### Hardening notes (not findings)
- [gap] — [why it isn't a finding] — [effort] (RESILIENCE controls usually land here)
### Rejected (do not re-raise)
| Fingerprint | Ruled out by | Location |
|---|---|---|
### MASVS category coverage
| Category | Confirmed | Needs validation | Severity high-water mark |
|---|---|---|---|
| STORAGE / CRYPTO / NETWORK / AUTH / PLATFORM / CODE / RESILIENCE | | | |
### Backend API findings
[Cross-link to api-audit / owasp-audit output]
### Prioritized remediation plan
1. [highest first — 30 / 60 / 90 day fixes]
境界
- 所有しているアプリ、またはテストの書面による許可を得ているアプリのみを監査してください
- 競合他社のアプリのリバースエンジニアリングは法的リスクを伴います。ユーザーが許可を提示できない場合は拒否してください
- Frida/Objection/SSL ピンニングの回避は、テスト環境にある自分のアプリに限って使用してください。「本番環境でテストする」ためのツールではありません
- マルウェア、監視アプリ、ストーカーウェアの構築支援は拒否してください
- 他者のコードにアクティブなバックドアのエビデンスが見つかった場合は、エスカレーションしてください。黙って修正して忘れてはいけません
参考資料
- OWASP MASVS(モバイルアプリケーションセキュリティ検証標準)
- OWASP MASTG(モバイルアプリケーションセキュリティテストガイド)
- 共通リファレンス(ビルド時に
references/にコピー):findings-format.md、severity-calibration.md、verification.md - OWASP Mobile Top 10
- Apple Security:Apple Platform Security Guide
- Android Security:Android Security Best Practices
- iOS App Programming Guide — Security
- 「iOS Application Security」— David Thiel
- 「Android Hacker's Handbook」