mcpField
I
ios-redteam-pipeline

ios-redteam-pipeline

github.com/elementalsouls安全5.3k193 次安装今天更新
代码仓库

关于 ios-redteam-pipeline

分阶段评估 iOS 应用的安全测试技能,涵盖应用盘点、IPA 获取、静态分析和运行时分析。它检查密钥、传输安全、URL 处理与网络流量,适用于获授权的移动端评估。

主要功能

  1. 01盘点组织拥有的 iOS 应用
  2. 02获取并解包 IPA 构建
  3. 03扫描二进制中的端点与密钥
  4. 04检查 ATS 和证书固定
  5. 05测试 URL Scheme 与 Universal Links
  6. 06支持运行时插桩和流量捕获

适用场景

  1. 01评估漏洞赏金范围内的 iOS 应用
  2. 02比较 TestFlight 与 App Store 构建
  3. 03检查移动应用传输安全和深层链接
  4. 04测试时追踪应用网络流量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill ios-redteam-pipeline

安装后在 Claude Code 中输入/ios-redteam-pipeline确认已加载。

详细介绍

适用场景

符合以下条件时触发:

  • 侦察发现目标的 Apple Developer / App Store 发布者页面下有 1 个或多个应用
  • 找到 TestFlight 公共链接或企业版/临时版 .ipa/manifest.plist(OTA 安装)
  • 面向客户的应用、经销商/合作伙伴门户或员工移动配套应用已在 iOS 上发布
  • 漏洞赏金计划将 iOS 列入范围
  • apk-redteam-pipeline 已发现 Android 端点/密钥——iOS 版本通常采用不同的后端版本,值得进行差异比对(参见 hunt-shadow-api)

请勿用于:

  • 仅支持 Android 的目标——应使用 apk-redteam-pipeline
  • 已通过 Web 端的 JS 包分析完全覆盖的 React Native / Flutter 应用
  • 评估范围内没有移动客户端的纯服务端评估

阶段 0 — 清点组织拥有的所有 iOS 应用

# App Store search API (no auth, no scraping needed)
curl -s "https://itunes.apple.com/search?term=<brand>&country=us&entity=software&limit=50" | python3 -m json.tool

# Pull the full metadata for a known bundle ID (once you have one)
curl -s "https://itunes.apple.com/lookup?bundleId=com.<brand>.app&country=us"

提取:trackId、bundleId、sellerName(开发者账户——可据此查找同属该账户的其他应用)、version、 releaseNotes(更新日志常会提及已弃用/移除的 API 行为,可为 hunt-shadow-api 提供线索)。

将 Android APK 清单中发现的同属该组织的应用 bundle ID 进行交叉比对(同一 多品牌企业集团通常会在两个平台上沿用 com.<corp>.<sub-brand> 命名方式)。


阶段 1 — 获取 IPA

首选:从你控制的真实设备获取(已购买/免费应用无需越狱)
# Install the app on a real device via Apple Configurator 2 or Xcode, then pull the .ipa
# Apple Configurator 2 (macOS): Devices > select device > right-click installed app > "Save to..."
# Or via libimobiledevice:
brew install libimobiledevice ideviceinstaller
ideviceinstaller -l              # list installed apps + bundle IDs
次选:TestFlight(如果该计划公开分发测试版)

打开 TestFlight 公共链接,通过 TestFlight 应用安装,然后按上述方法提取。 TestFlight 版本的防护通常比 App Store 发布版本弱得多(调试日志未关闭、 硬编码了预发布 API 主机)——如果两种版本都有,应始终优先使用 TestFlight 版本,而非商店版本。

第三选择:企业版 / 临时分发(OTA 安装)
# itms-services:// links embed a manifest.plist with a direct .ipa URL
curl -s "https://<target>/manifest.plist" | plutil -convert xml1 -o - -
# Look for <key>software-package</key> — that URL is a directly downloadable, unencrypted IPA
curl -sk -L "<software-package-url>" -o target.ipa

企业版/临时版 IPA 未使用 FairPlay 加密——无需越狱或解密工具, 这与从设备提取的 App Store 二进制文件不同。

解密来自 App Store 的二进制文件(仅限从越狱设备中提取的情况)

App Store 二进制文件在静态存储时经过 FairPlay 加密;从越狱设备复制的二进制文件 需要先进行运行时解密(使用 frida-ios-dump、bagbak 或 flexdecrypt),静态分析工具才能 有效读取:

pip install --break-system-packages frida-tools
# with frida-server running on the jailbroken device and the app in foreground:
python3 dump.py <bundle_id>          # frida-ios-dump — outputs a decrypted .ipa

阶段 2 — 解包与静态分析

# An IPA is just a zip
unzip -o target.ipa -d extracted_target/
cd extracted_target/Payload/*.app

# Info.plist — bundle ID, URL schemes, ATS config, entitlements hint
plutil -convert xml1 -o - Info.plist

# Entitlements — codesign reads the .app bundle (or the Mach-O binary), NOT Info.plist
codesign -d --entitlements :- Payload/<AppName>.app 2>/dev/null || \
  security cms -D -i embedded.mobileprovision | plutil -convert xml1 -o - -

# class-dump for Objective-C symbol/class recovery (compiled binary, not the .app bundle)
brew install class-dump
class-dump -H <AppBinaryName> -o headers/

# Swift binaries: class-dump won't show much — use Hopper, Ghidra, or `nm`/`strings` instead
nm -a <AppBinaryName> | grep -i swift | head -50
strings -a <AppBinaryName> > strings_target.txt

如需快速初步排查,无需反汇编工具,单独导出字符串通常就能发现 阶段 3 要查找的大部分内容。


阶段 3 — 搜索密钥(与 apk-redteam-pipeline 使用相同的清单,另加 iOS 专属来源)

# URL grep — owned-domain references
grep -oE 'https?://[a-zA-Z0-9.-]+\.(target1|target2|target3)\.(com|io|net)[a-zA-Z0-9./_?=&%-]*' strings_target.txt | sort -u

# Cloud credentials (same 60-pattern catalog as Android — reuse verbatim)
grep -oE 'AKIA[A-Z0-9]{16}'                             # AWS Access Key
grep -oE 'AIza[A-Za-z0-9_-]{35}'                        # Google API key
grep -oE 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*' strings_target.txt   # JWT

# iOS-specific: GoogleService-Info.plist (Firebase config bundled per-platform)
find extracted_target -iname "GoogleService-Info.plist" -exec plutil -convert xml1 -o - {} \;
# Look for API_KEY, PROJECT_ID, STORAGE_BUCKET, GCM_SENDER_ID, GOOGLE_APP_ID — same Firebase
# public-read tests as apk-redteam-pipeline Stage 6.

# iOS-specific: hardcoded config plists shipped in the bundle
find extracted_target -iname "*.plist" ! -iname "Info.plist" -exec sh -c 'echo "=== {} ==="; plutil -convert xml1 -o - "{}"' \;

# App Transport Security exceptions (Info.plist) — tells you if arbitrary/insecure loads are allowed
plutil -extract NSAppTransportSecurity xml1 -o - Info.plist 2>/dev/null
备份中残留的钥匙串项目(如果你有设备备份,无论是否加密)
pip install --break-system-packages iphone_backup_decrypt   # for encrypted local backups
# keychain-dumper (run ON a jailbroken device) for live keychain contents:
./keychain-dumper -e   # -e also decodes entitlements per item, showing which app owns which secret

阶段 4 — 应用传输安全(ATS)配置错误与证书固定绕过

检查是否全局禁用了 ATS(最常见的 iOS 网络配置错误)
plutil -extract NSAppTransportSecurity xml1 -o - Info.plist

输出中的危险信号:

  • 顶层设置 NSAllowsArbitraryLoads = true——任何位置都允许使用 HTTP(明文传输),影响整个应用。
  • 对承载身份验证令牌的域设置了 NSExceptionAllowsInsecureHTTPLoads = true。
  • 设置了 NSAllowsArbitraryLoadsInWebContent = true——WKWebView 流量被排除在 ATS 保护之外,这是常见的盲区。

全局 ATS 例外配置加上处于网络中间位置(恶意接入点、ARP 欺骗、恶意 VPN 配置文件), 即可在完全不触及证书固定机制的情况下拦截明文凭据/令牌。

证书固定绕过(已启用且配置正确时)
pip install --break-system-packages frida-tools objection
objection --gadget <bundle_id> explore
# inside objection:
ios sslpinning disable

如果你想用 Frida 脚本,请勿自行编写,而应使用维护中的通用绕过脚本 (例如广泛使用的 frida-ios-pinning/ios-ssl-bypass 社区脚本)。现代 iOS TLS 流量会经过 BoringSSL,因此可靠的通用 Hook 会在原生层针对 SSL_CTX_set_custom_verify / SSL_get_psk_identity,并强制验证回调返回“OK”——这样可一次覆盖 URLSession、AFNetworking、 Alamofire 和 TrustKit,而按委托分别设置的 Objective-C Hook(例如已弃用的 NSURLConnection 委托)则无法做到:

# Pull a maintained universal BoringSSL-layer bypass and run it:
frida -U -f <bundle_id> -l ios-ssl-bypass.js --no-pause

实际使用时,优先选择 SSL Kill Switch 2(越狱设备上以 tweak 形式安装)或 objection 的 ios sslpinning disable,不要使用自行编写的脚本——两者都能覆盖常见的 证书固定实现(NSURLSession、AFNetworking、TrustKit),无需针对每个应用单独调整。


阶段 5 — URL scheme / Universal Link 枚举

# Custom URL schemes (CFBundleURLTypes) — anything can invoke these via Safari/another app
plutil -extract CFBundleURLTypes xml1 -o - Info.plist

# Universal Links / Associated Domains (applinks:) — requires a matching apple-app-site-association
plutil -extract com.apple.developer.associated-domains xml1 -o - Info.plist 2>/dev/null
curl -s "https://<domain>/.well-known/apple-app-site-association" | python3 -m json.tool

对发现的每个自定义 scheme(例如 myapp://):

  • 从 Safari/Notes 触发它,并观察应用如何处理参数: myapp://reset-password?token=x&redirect=https://evil.com——应用是否信任 攻击者提供的 redirect/url/callback 参数,并在 WebView 中加载该地址(开放重定向 → WebView-XSS 攻击链),或利用它绕过身份验证界面?
  • 如果设备上的其他应用也注册了该 scheme(scheme squatting),恶意应用就能拦截原本发给合法应用的流量——检查 CFBundleURLName 是否唯一。
  • Universal Links 在 AASA 验证失败或缺失时会回退到自定义 scheme——针对同一参数注入攻击面测试这两条路径。

阶段 6 — 运行时插桩(Frida / objection)

需要越狱设备(旧版 iOS 可使用 checkra1n/palera1n,或使用 Corellium 虚拟设备)—— 与 Android 不同,iOS 没有实用的 Root 模拟器替代方案。

# Setup
pip install --break-system-packages frida-tools objection
# Install frida-server on the jailbroken device via Cydia/Sileo (frida repo), matching the
# host frida-tools version exactly — version skew is the #1 cause of "failed to attach" errors.

# Full interactive exploration
objection --gadget <bundle_id> explore
# Inside objection:
ios hooking watch class <ClassName>
ios hooking watch class_method <Class>.<method> --dump-args --dump-return
ios keychain dump
ios plist dump
ios cookies get
网络流量捕获(绕过证书固定后)
mitmproxy --listen-port 8080
# Set the device Wi-Fi proxy to host:8080, install the mitmproxy CA via http://mitm.it on-device
# (Settings > General > VPN & Device Management > trust the cert, then enable full trust under
# Certificate Trust Settings — iOS requires this second step, unlike Android)

决策树 — 根据发现采取行动

发现后续操作
NSAllowsArbitraryLoads = true确认令牌/凭据是否确实通过 HTTP 传输——利用它需要处于网络路径上,但其本身就是有效发现(配置层面的问题,无需 MITM 即可报告)
字符串转储中存在硬编码的 JWT / API 密钥与 Android 相同——针对 API 主机测试,并串联至 hunt-api-misconfig
存在 GoogleService-Info.plist测试 Firestore/RTDB/Storage 是否可公开读取(与 apk-redteam-pipeline 阶段 6 相同)
自定义 URL scheme 接受 redirect/url 参数测试开放重定向 → WebView 加载攻击链;检查其他已安装应用是否存在 scheme squatting
Universal Link 的 AASA 缺失/配置错误确认 scheme 回退仍会携带相同的可注入参数
Entitlements 显示 keychain-access-groups 与其他应用共享跨应用读取 Keychain——受攻击的关联应用可读取此应用的机密信息
引用的是较旧的 API 版本,而当前 Web 应用调用的是另一版本转交给 hunt-shadow-api 进行版本差异分析

反模式

  • 不要认为 App Store 应用都经过 FairPlay 加密,因此需要越狱——TestFlight 和企业版/Ad Hoc 构建通常未加密,完全不需要解密步骤。先确认分发渠道,再考虑使用 frida-ios-dump。
  • 不要因为 class-dump 没有显示内容,就忽略 Swift 二进制文件——strings 和 nm 仍然可用;使用支持 Swift 的反汇编工具(Hopper、启用了 Swift 符号反混淆的 Ghidra)可恢复其余内容。
  • 不要只把“存在证书固定”当作发现——证书固定是一种缓解措施,并非漏洞;真正的发现是在绕过后能做什么(或者让证书固定失效的 ATS 错误配置)。
  • 不要忽略由 WKWebView 加载的内容——NSAllowsArbitraryLoadsInWebContent 与顶层 ATS 设置是不同的例外,且经常被忽略。
  • 不要在个人/生产环境的 Apple ID 设备上运行 Frida 插桩——使用专用的越狱测试设备或 Corellium 实例。

工具安装(一次性)

brew install libimobiledevice ideviceinstaller class-dump
pip install --break-system-packages frida-tools objection iphone_backup_decrypt
# Jailbroken test device (checkra1n/palera1n) or a Corellium virtual iOS device for runtime work
# frida-server installed on-device via the Frida Cydia/Sileo repo

相关技能与链路

  • apk-redteam-pipeline——Android 对应方案;如果目标同时提供两个平台的版本,请同时运行二者。同源的 Bundle ID 和共用的后端端点经常会揭示跨平台问题。
  • hunt-shadow-api——移动端构建版本(iOS 和 Android 均如此)中硬编码的 API 版本通常比当前 Web 应用旧。链路:IPA 揭示 /v1/* 端点 → hunt-shadow-api 对比 /v1/ 与当前的 /v3/,查找身份验证/验证逻辑回归。
  • cloud-iam-deep——从 IPA 提取的密钥经常会包含有效的 AWS/GCP/Azure 凭据或 Firebase 配置。链路:通过 strings-grep 找到 AWS 密钥 → 使用 cloud-iam-deep 进行权限分析。
  • hunt-api-misconfig——在此处提取的硬编码 JWT/API 密钥可直接用于该工具中的 JWT 算法混淆和批量赋值测试。
  • evidence-hygiene——将提取的 Keychain 项目和密钥纳入报告前,需要先进行脱敏。
  • offensive-osint——枚举 App Store 开发者页面是更广泛的组织侦察图谱的一部分;可与针对同一品牌的证书透明度查询配合使用。

评论

支持 Markdown