ios-pentesting-tricks について
iOS アプリを評価するセキュリティテスター向けの手引きです。脱獄・非脱獄の両方を扱い、キーチェーン、リンク、ランタイム操作、バイナリ保護、データ保存を解説します。
主な機能
- 01脱獄・非脱獄環境でのテスト方法
- 02キーチェーン抽出と保護クラス分析
- 03URL スキームと Universal Links の検査
- 04Frida と Objection によるランタイム操作
- 05バイナリ保護とデータ保存の分析
活用シーン
- 01iOS アプリの認証情報保存の評価
- 02OAuth コールバックとディープリンクのリスク検証
- 03ランタイム防御とバイナリセキュリティの確認
- 04ローカルキャッシュ内の機密データの調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill ios-pentesting-tricksインストール後、Claude Code で/ios-pentesting-tricksを入力して読み込まれたか確認します。
同梱ファイルIOS_RUNTIME_TRICKS.md
詳細
スキル:iOS ペンテストのテクニック — エキスパート向け攻撃プレイブック
AI LOAD INSTRUCTION:iOS アプリケーションのセキュリティテストに関するエキスパート向けテクニックです。脱獄環境と非脱獄環境での手法、キーチェーンの抽出、URL スキーム/ユニバーサルリンクの悪用、Frida/Objection のランタイムフック、バイナリの保護チェック、データストレージの分析を取り上げます。ベースモデルでは、保護クラスの細かな違いや AASA の設定ミスのパターンを見落としがちです。
0. 関連するルーティング
詳しく調べる前に、以下の読み込みを検討してください。
- mobile-ssl-pinning-bypass:詳細な SSL ピンニング回避(SecTrust フック、SSL Kill Switch、フレームワーク固有のテクニック)
- android-pentesting-tricks:同じアプリの Android 版もテストする場合
- api-sec:通信を傍受した後のバックエンド API セキュリティテスト
高度なリファレンス
以下が必要な場合は、IOS_RUNTIME_TRICKS.md も読み込んでください。
- iOS 固有のフックに関する Frida のレシピ(ObjC クラスの列挙、メソッドのスウィズリング)
- iOS 用 Objection コマンドのリファレンス
- ランタイムフックのパターンと回避テンプレート
1. 脱獄環境と非脱獄環境でのテスト
| 機能 | 脱獄環境 | 非脱獄環境 |
|---|---|---|
| SSL ピンニングの回避 | Frida、SSL Kill Switch 2、Objection | ネットワークデバッグプロキシ、MITM プロファイル(制限あり) |
| キーチェーンへのアクセス | keychain-dumper、Frida によるダンプ | バックアップからの抽出のみ(制限あり) |
| ファイルシステムの調査 | アプリのサンドボックスへのフルアクセス | ideviceinstaller + バックアップのみ |
| ランタイムの操作 | Frida、Cycript、LLDB のアタッチ | サイドロードしたアプリで Frida を使用(再署名が必要) |
| バイナリ解析 | Class-dump、デバイス上の Hopper | Mac で IPA を復号し、オフラインで解析 |
| メソッドフック | Frida/Cycript の全機能 | 制限あり(再署名したアプリ + Frida gadget が必要) |
非脱獄環境でのテスト設定
# Extract IPA from device
ideviceinstaller -l # List installed apps
ios-deploy --id <UDID> --download --bundle_id com.target.app
# Or use frida-ios-dump for decrypted IPA (jailbroken)
python dump.py com.target.app
# Sideload with Frida gadget (non-jailbreak runtime hooking)
# 1. Extract IPA, 2. Insert FridaGadget.dylib into Frameworks/
# 3. Re-sign with valid profile, 4. Install via ios-deploy
2. キーチェーンの抽出
2.1 キーチェーンの保護クラス
| 保護クラス | 利用可能な条件 | 用途 | リスクレベル |
|---|---|---|---|
kSecAttrAccessibleWhenUnlocked | デバイスのロック解除中のみ | パスワード、トークン | 中 |
kSecAttrAccessibleAfterFirstUnlock | 初回ロック解除後、再起動まで | バックグラウンド用トークン | 高(ロック後も保持される) |
kSecAttrAccessibleAlways | 常時(iOS 12 以降では非推奨) | レガシーアプリ | 重大 |
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly | パスコード設定済みかつロック解除中 | 重要度の高い秘密情報 | 低 |
2.2 抽出方法
# Jailbroken: keychain-dumper
/path/to/keychain-dumper -a # Dump all accessible items
/path/to/keychain-dumper -g password # Generic passwords only
/path/to/keychain-dumper -i # Internet passwords
# Frida / Objection
objection -g com.target.app explore
> ios keychain dump
> ios keychain dump --json # JSON output for parsing
# Frida script for keychain enumeration
frida -U -f com.target.app -l keychain_dump.js
2.3 確認する項目
| 項目の種類 | キーチェーンクラス | 一般的な内容 |
|---|---|---|
kSecClassGenericPassword | genp | アプリのトークン、API キー、ユーザー認証情報 |
kSecClassInternetPassword | inet | HTTP 認証情報、OAuth トークン |
kSecClassCertificate | cert | クライアント証明書 |
kSecClassIdentity | idnt | 証明書 + 秘密鍵のペア |
kSecClassKey | keys | 暗号化キー |
3. URL スキームのハイジャック
3.1 カスタム URL スキームの特定
# From IPA/app bundle — check Info.plist
plutil -p /path/to/Payload/Target.app/Info.plist | grep -A 10 CFBundleURLTypes
# Example output:
# "CFBundleURLSchemes" => ["targetapp", "fb123456789"]
3.2 ハイジャック攻撃
Scenario: Target app registers "targetapp://" for OAuth callback
1. Attacker app also registers "targetapp://" URL scheme
2. User initiates OAuth login in target app
3. OAuth provider redirects to targetapp://callback?code=AUTH_CODE
4. iOS may open attacker's app instead (non-deterministic scheme resolution)
5. Attacker captures OAuth authorization code
| 攻撃ベクトル | 手法 | 影響 |
|---|---|---|
| OAuth コールバックの傍受 | 同じスキームを登録 | 認可コードの窃取 |
| ディープリンクのハイジャック | 同じスキームを登録 | フィッシング、データの傍受 |
| 決済コールバックの傍受 | 決済スキームを登録 | 取引の改ざん |
3.3 URL スキームとユニバーサルリンクのセキュリティ
| 機能 | カスタム URL スキーム | ユニバーサルリンク |
|---|---|---|
| 登録 | どのアプリでも任意のスキームを登録できる | ドメイン上の AASA ファイルが必要 |
| 一意性 | 保証されない(複数のアプリが登録可能) | ドメインパスごとに 1 つのアプリ |
| 検証 | なし | 暗号学的(AASA に署名) |
| 推奨用途 | 機密性の低いナビゲーション | OAuth コールバック、機密性の高い操作 |
| ハイジャック可能性 | あり(重複登録) | AASA の設定ミスがある場合のみ |
4. ユニバーサルリンクの悪用
4.1 AASA(Apple-App-Site-Association)の設定ミス
# Fetch AASA file
curl -s "https://target.com/.well-known/apple-app-site-association" | jq .
curl -s "https://target.com/apple-app-site-association" | jq .
# Check for wildcard patterns (overly broad)
# Bad: "paths": ["*"] ← captures ALL URLs
# Bad: "paths": ["/NOT *"] ← poorly written exclusion
| 設定ミス | リスク | 悪用方法 |
|---|---|---|
ワイルドカードパス(*) | アプリがドメイン上のすべてのURLを要求します | リダイレクトチェーンがUniversal Linksを妨げ、URLスキームへのフォールバックを引き起こす可能性があります |
| AASAファイルがない | Universal Linksが機能しません | アプリがセキュリティの低いURLスキームにフォールバックします |
| AASAが誤ったドメインにある | リンクが関連付けられません | スキームハイジャックが可能です |
AASAがapplication/jsonとして配信されない | 解析に失敗します | リンクが関連付けられません |
| CDNが古いAASAをキャッシュしている | 関連付けが古くなります | 動作に一貫性がなくなります |
4.2 Universal LinksからURLスキームへのフォールバックの妨害
Technique: Force Universal Link to not open app, causing fallback to URL scheme
1. User long-presses link → "Open in Safari" (disables UL for that domain)
2. Redirect chain: domain A → domain B → target (UL breaks on redirect)
3. JavaScript redirect instead of 302 (UL only works on server-side redirects)
4. App not installed → URL scheme fallback → hijackable
5. ランタイム操作
5.1 iOSでのFrida
# Connect to app on jailbroken device
frida -U -f com.target.app --no-pause
# Basic ObjC exploration
> ObjC.classes # List all classes
> ObjC.classes.NSURLSession # Check if class exists
> ObjC.classes.AppDelegate.$methods # List methods
> ObjC.classes.AppDelegate['- isLoggedIn'].implementation # Read method
# Hook method and modify return value
Interceptor.attach(ObjC.classes.AuthManager['- isAuthenticated'].implementation, {
onLeave: function(retval) {
retval.replace(ptr(1)); // Force return TRUE
}
});
5.2 ObjectionのiOSコマンド
objection -g com.target.app explore
# Keychain
> ios keychain dump
# Cookies
> ios cookies get
# Pasteboard
> ios pasteboard monitor
# Jailbreak detection bypass
> ios jailbreak disable
# SSL pinning bypass
> ios sslpinning disable
# Binary info
> ios info binary
# Hooking
> ios hooking watch class AppDelegate
> ios hooking watch method "-[AuthManager isAuthenticated]" --dump-args --dump-return
> ios hooking set return_value "-[AuthManager isJailbroken]" false
5.3 Cycript(レガシーですが有用)
// Attach to running app
cycript -p com.target.app
// Explore UI hierarchy
UIApp.keyWindow.recursiveDescription().toString()
// Find view controllers
[UIWindow.keyWindow().rootViewController _printHierarchy].toString()
// Call methods directly
[AppDelegate.sharedInstance isLoggedIn] // → check return
AppDelegate.sharedInstance.isLoggedIn = true // → modify
// Access singleton instances
var vc = choose(LoginViewController)[0]
vc.bypassLogin()
6. バイナリ保護
6.1 バイナリセキュリティの確認
# PIE (Position Independent Executable)
otool -hv /path/to/binary | grep PIE
# ARC (Automatic Reference Counting)
otool -I -v /path/to/binary | grep objc_release
# Stack canaries
otool -I -v /path/to/binary | grep __stack_chk_guard
# Encryption (FairPlay DRM)
otool -l /path/to/binary | grep -A 4 LC_ENCRYPTION_INFO
# cryptid 0 = decrypted, cryptid 1 = encrypted
| 保護機能 | 確認方法 | 欠如した場合の影響 |
|---|---|---|
| PIE | ヘッダー内のMH_PIEフラグ | ASLRが無効になり、アドレスを予測しやすくなります |
| ARC | _objc_releaseシンボル | Use-after-freeが発生しやすくなります |
| スタックカナリア | __stack_chk_guard | バッファーオーバーフローを悪用しやすくなります |
| 暗号化 | cryptidの値 | 復号せずにバイナリを読み取れます |
6.2 IPAの復号
# frida-ios-dump (preferred, jailbroken device)
python dump.py com.target.app
# Outputs: decrypted IPA in current directory
# bagbak (alternative)
bagbak com.target.app
# Manual via Frida
frida -U -f com.target.app -l dump_memory.js
# Dump decrypted binary from memory, replace encrypted section
6.3 ObjC解析用のClass-dump
# Dump Objective-C class information
class-dump /path/to/decrypted/binary > classes.h
class-dump -H /path/to/decrypted/binary -o /tmp/headers/
# Search for interesting patterns
grep -r "password\|token\|secret\|apiKey\|isJailbroken\|isRooted" /tmp/headers/
7. データストレージの問題
7.1 機密データの保存場所
| 場所 | パス | 確認対象 |
|---|---|---|
| NSUserDefaults | Library/Preferences/<bundle-id>.plist | トークン、ユーザーデータ、機能フラグ |
| Core Data(SQLite) | Library/Application Support/*.sqlite | キャッシュされたAPIレスポンス、ユーザーレコード |
| Keychain | システムキーチェーンデータベース | 認証情報、キー(保護クラスを確認) |
| Cookies | Library/Cookies/Cookies.binarycookies | セッションCookie |
| キャッシュ | Library/Caches/ | キャッシュされたAPIレスポンス、PIIを含む画像 |
| スクリーンショット | Library/SplashBoard/Snapshots/ | バックグラウンド移行時にキャプチャされたアプリの状態 |
| キーボードキャッシュ | Library/Keyboard/ | 機密情報を含む入力のオートコンプリート候補 |
| ペーストボード | システムペーストボード | コピーされたパスワード、トークン |
| WebViewストレージ | Library/WebKit/WebsiteData/ | LocalStorage、IndexedDB、Cookie |
7.2 調査コマンド
# On jailbroken device — app sandbox at:
# /var/mobile/Containers/Data/Application/<UUID>/
# Find app UUID
find /var/mobile/Containers -name "com.target.app" 2>/dev/null
# Check NSUserDefaults
plutil -p Library/Preferences/com.target.app.plist
# Check SQLite databases
sqlite3 Library/Application\ Support/Model.sqlite ".tables"
sqlite3 Library/Application\ Support/Model.sqlite "SELECT * FROM ZUSER;"
# Check for sensitive strings in all files
grep -r "password\|token\|bearer\|api_key" Documents/ Library/
8. 通信セキュリティ(ATS)
8.1 ATS例外のパターン
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>insecure-api.target.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
</dict>
</dict>
</dict>
| ATS設定 | リスク | 備考 |
|---|---|---|
NSAllowsArbitraryLoads = true | 重大 | すべてのHTTP通信が許可されます |
NSExceptionAllowsInsecureHTTPLoads | 高 | 特定のドメインでHTTPを許可します |
NSExceptionMinimumTLSVersion = TLSv1.0 | 中 | 脆弱なTLSです |
NSAllowsArbitraryLoadsInWebContent | 中 | WebViewでHTTPを読み込めます |
| ATS例外なし | 低 | 適切な設定です |
9. iOSペネトレーションテストの判断ツリー
Testing iOS application
│
├── Device jailbroken?
│ ├── Yes → full testing capability
│ │ ├── Keychain dump → ios keychain dump (§2)
│ │ ├── Filesystem inspection → check all data storage (§7)
│ │ ├── Runtime hooks → Frida/Objection (§5)
│ │ └── Binary analysis → class-dump decrypted binary (§6)
│ └── No → limited testing
│ ├── Re-sign with Frida gadget for runtime access
│ ├── Backup extraction for data analysis
│ └── Network-level testing (proxy + SSL bypass)
│
├── SSL pinning blocking proxy?
│ └── Yes → see mobile-ssl-pinning-bypass SKILL.md
│
├── URL schemes registered?
│ ├── OAuth callback via URL scheme? → hijacking risk (§3.2)
│ ├── Universal Links configured? → check AASA (§4.1)
│ └── Scheme used for sensitive actions? → test interception
│
├── Binary protections adequate?
│ ├── Missing PIE? → ASLR disabled (§6.1)
│ ├── No stack canaries? → overflow risk (§6.1)
│ └── Still encrypted? → decrypt first (§6.2)
│
├── Data storage secure?
│ ├── Tokens in NSUserDefaults? → plaintext extraction (§7.1)
│ ├── Keychain protection class? → AfterFirstUnlock = risky (§2.1)
│ ├── Screenshots captured? → check Snapshots dir (§7.1)
│ └── Keyboard cache? → check for sensitive autocomplete (§7.1)
│
├── ATS configured?
│ ├── ArbitraryLoads = true? → HTTP downgrade possible (§8)
│ └── Domain exceptions? → targeted HTTP interception
│
└── Runtime manipulation needed?
├── Jailbreak detection blocking? → ios jailbreak disable (§5.2)
├── Need to bypass auth check? → hook + modify return (§5.1)
└── Need to trace API calls? → method hooking (§5.2)
コメント
Markdown 対応