关于 ios-pentesting-tricks
面向 iOS 应用安全测试人员的渗透测试技巧手册,覆盖越狱与非越狱方法。内容聚焦 Keychain、链接处理、运行时操作、二进制防护和数据存储检查。
主要功能
- 01越狱与非越狱测试方法
- 02Keychain 提取与保护类分析
- 03URL Scheme 和 Universal Links 检查
- 04Frida、Objection 运行时操作
- 05二进制防护与数据存储分析
适用场景
- 01评估 iOS 应用的凭据存储
- 02测试 OAuth 回调和深层链接风险
- 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 加载指令:iOS 应用安全测试专家技术。涵盖越狱与非越狱测试方法、钥匙串提取、URL scheme/通用链接滥用、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 类枚举、方法调配)
- Objection iOS 命令参考
- 运行时钩子模式和绕过模板
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 scheme 劫持
3.1 自定义 URL scheme 发现
# 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 回调拦截 | 注册相同 scheme | 窃取授权码 |
| 深度链接劫持 | 注册相同 scheme | 网络钓鱼、数据拦截 |
| 支付回调拦截 | 注册支付 scheme | 操纵交易 |
3.3 URL scheme 与通用链接的安全性对比
| 特性 | 自定义 URL scheme | 通用链接 |
|---|---|---|
| 注册 | 任何应用都可声明任何 scheme | 需要域名上的 AASA 文件 |
| 唯一性 | 不保证(可有多个应用) | 每个域名路径对应一个应用 |
| 验证 | 无 | 加密验证(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
| 配置错误 | 风险 | 利用方式 |
|---|---|---|
通配符路径(*) | App 声明域名上的所有 URL | 重定向链可能中断 UL → 回退到 URL scheme |
| 缺少 AASA 文件 | 通用链接无法使用 | App 回退到安全性较低的 URL scheme |
| AASA 位于错误的域名 | 链接未关联 | 可能发生 scheme 劫持 |
AASA 未以 application/json 格式提供 | 解析失败 | 链接无法关联 |
| CDN 缓存了过时的 AASA | 关联信息过时 | 行为不一致 |
4.2 通用链接失效 → 回退到 URL Scheme
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 符号 | 更容易发生释放后使用 |
| 栈金丝雀 | __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 使用 class-dump 分析 ObjC
# 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 | 系统钥匙串数据库 | 凭据、密钥(检查保护类) |
| Cookie | Library/Cookies/Cookies.binarycookies | 会话 Cookie |
| 缓存 | Library/Caches/ | 缓存的 API 响应、包含 PII 的图像 |
| 屏幕快照 | Library/SplashBoard/Snapshots/ | 后台运行时捕获的 App 状态 |
| 键盘缓存 | 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