ios-redteam-pipeline

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

When to use this skill

何时使用此 skill

Trigger when:
  • Recon surfaces 1+ apps under the target's Apple Developer / App Store publisher page
  • A TestFlight public link or enterprise/ad-hoc
    .ipa
    /
    manifest.plist
    (OTA install) is found
  • Customer-facing app, dealer/partner portal, or employee mobile companion app ships on iOS
  • Bug bounty program lists iOS in scope
  • apk-redteam-pipeline
    already found Android endpoints/secrets — the iOS build often ships a different backend version worth diffing (see
    hunt-shadow-api
    )
DO NOT use for:
  • Android-only targets — that's
    apk-redteam-pipeline
  • React Native / Flutter apps already fully covered by JS-bundle analysis on the web side
  • Server-side only assessments with no mobile client in scope

出现以下情况时触发:
  • 侦察发现目标的 Apple Developer / App Store 发布者页面下有 1 个或多个应用
  • 发现 TestFlight 公共链接,或企业/ad-hoc
    .ipa
    /
    manifest.plist
    (OTA 安装)
  • 面向客户的应用、经销商/合作伙伴门户或员工移动配套应用在 iOS 上发布
  • 漏洞赏金项目将 iOS 列入范围
  • apk-redteam-pipeline
    已发现 Android 端点/机密——iOS 构建通常搭载不同的后端版本,值得进行差异比较(见
    hunt-shadow-api
    )
不要用于:
  • 仅支持 Android 的目标——应使用
    apk-redteam-pipeline
  • Web 端的 JS bundle 分析已完全覆盖的 React Native / Flutter 应用
  • 范围内没有移动客户端的纯服务端评估

Stage 0 — Inventory all org-owned iOS apps

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

bash
undefined
bash
undefined

App Store search API (no auth, no scraping needed)

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
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)

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"

Extract: `trackId`, `bundleId`, `sellerName` (developer account — pivot to find sibling apps), `version`,
`releaseNotes` (changelogs often reference deprecated/removed API behavior — feeds `hunt-shadow-api`).

Cross-reference sibling-app bundle IDs surfaced from Android APK inventories (same
multi-brand conglomerate usually reuses `com.<corp>.<sub-brand>` naming on both platforms).

---
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>` 命名)。

---

Stage 1 — IPA acquisition

阶段 1 — IPA 获取

Primary: from a real device you control (no jailbreak needed for a purchased/free app)

主要方式:从你控制的真机获取(对于已购买或免费的应用,无需越狱)

bash
undefined
bash
undefined

Install the app on a real device via Apple Configurator 2 or Xcode, then pull the .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..."

Apple Configurator 2 (macOS): Devices > select device > right-click installed app > "Save to..."

Or via libimobiledevice:

Or via libimobiledevice:

brew install libimobiledevice ideviceinstaller ideviceinstaller -l # list installed apps + bundle IDs
undefined
brew install libimobiledevice ideviceinstaller ideviceinstaller -l # list installed apps + bundle IDs
undefined

Secondary: TestFlight (if the program distributes betas publicly)

次要方式:TestFlight(如果项目公开发布测试版)

Open the public TestFlight link, install via the TestFlight app, then extract as above. TestFlight builds are frequently LESS hardened than App Store releases (debug logging left on, staging API hosts hardcoded) — always prefer a TestFlight build over the Store build if both exist.
打开公共 TestFlight 链接,通过 TestFlight 应用安装,然后按上述步骤提取。 TestFlight 构建的加固程度通常低于 App Store 发布版本(可能保留调试日志、硬编码 staging API 主机)——如果两者都存在,始终优先使用 TestFlight 构建,而不是 Store 构建。

Tertiary: enterprise / ad-hoc distribution (OTA install)

第三种方式:企业/ad-hoc 分发(OTA 安装)

bash
undefined
bash
undefined

itms-services:// links embed a manifest.plist with a direct .ipa URL

itms-services:// links embed a manifest.plist with a direct .ipa URL

curl -s "https://<target>/manifest.plist" | plutil -convert xml1 -o - -
curl -s "https://<target>/manifest.plist" | plutil -convert xml1 -o - -

Look for <key>software-package</key> — that URL is a directly downloadable, unencrypted IPA

Look for <key>software-package</key> — that URL is a directly downloadable, unencrypted IPA

curl -sk -L "<software-package-url>" -o target.ipa
Enterprise/ad-hoc IPAs are **not FairPlay-encrypted** — no jailbreak or decryption tooling needed,
unlike an App Store binary pulled from a device.
curl -sk -L "<software-package-url>" -o target.ipa
`itms-services://` 链接会嵌入一个 `manifest.plist`,其中包含指向 `.ipa` 的直接 URL。
企业/ad-hoc IPA **不采用 FairPlay 加密**——与从真机提取的 App Store 二进制文件不同,无需越狱或解密工具。

Decrypting an App-Store-sourced binary (only if extracted from a jailbroken device)

解密 App Store 来源的二进制文件(仅当从越狱设备提取时)

App Store binaries are FairPlay-encrypted at rest; a binary copied off a jailbroken device needs runtime decryption (
frida-ios-dump
,
bagbak
, or
flexdecrypt
) before static tools can read it meaningfully:
bash
pip install --break-system-packages frida-tools
App Store 二进制文件在存储时采用 FairPlay 加密;从越狱设备复制出的二进制文件需要运行时解密(
frida-ios-dump
、
bagbak
或
flexdecrypt
),静态工具才能有意义地读取:
bash
pip install --break-system-packages frida-tools

with frida-server running on the jailbroken device and the app in foreground:

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

---
python3 dump.py <bundle_id> # frida-ios-dump — outputs a decrypted .ipa

---

Stage 2 — Unpack and static analysis

阶段 2 — 解包与静态分析

bash
undefined
bash
undefined

An IPA is just a zip

An IPA is just a zip

unzip -o target.ipa -d extracted_target/ cd extracted_target/Payload/*.app
unzip -o target.ipa -d extracted_target/ cd extracted_target/Payload/*.app

Info.plist — bundle ID, URL schemes, ATS config, entitlements hint

Info.plist — bundle ID, URL schemes, ATS config, entitlements hint

plutil -convert xml1 -o - Info.plist
plutil -convert xml1 -o - Info.plist

Entitlements — codesign reads the .app bundle (or the Mach-O binary), NOT 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 - -
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)

class-dump for Objective-C symbol/class recovery (compiled binary, not the .app bundle)

brew install class-dump class-dump -H <AppBinaryName> -o headers/
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

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

For a fast triage pass without a disassembler, the strings dump alone usually surfaces most of
what Stage 3 is looking for.

---
nm -a <AppBinaryName> | grep -i swift | head -50 strings -a <AppBinaryName> > strings_target.txt

如果不使用反汇编器进行快速初筛,仅 `strings` 转储通常就能找出阶段 3 所寻找的大部分内容。

---

Stage 3 — Secret grep (same catalog as apk-redteam-pipeline, iOS-specific sources added)

阶段 3 — 机密信息 grep(与 apk-redteam-pipeline 使用相同规则集,并新增 iOS 专用来源)

bash
undefined
bash
undefined

URL grep — owned-domain references

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
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)

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
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)

iOS-specific: GoogleService-Info.plist (Firebase config bundled per-platform)

find extracted_target -iname "GoogleService-Info.plist" -exec plutil -convert xml1 -o - {} ;
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

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.

public-read tests as apk-redteam-pipeline Stage 6.

iOS-specific: hardcoded config plists shipped in the bundle

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 - "{}"' ;
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

App Transport Security exceptions (Info.plist) — tells you if arbitrary/insecure loads are allowed

plutil -extract NSAppTransportSecurity xml1 -o - Info.plist 2>/dev/null
undefined
plutil -extract NSAppTransportSecurity xml1 -o - Info.plist 2>/dev/null
undefined

Keychain items left in a backup (if you have a device backup, encrypted or not)

备份中遗留的 Keychain 项(如果拥有设备备份,无论是否加密)

bash
pip install --break-system-packages iphone_backup_decrypt   # for encrypted local backups
bash
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 (run ON a jailbroken device) for live keychain contents:

./keychain-dumper -e # -e also decodes entitlements per item, showing which app owns which secret

---
./keychain-dumper -e # -e also decodes entitlements per item, showing which app owns which secret

---

Stage 4 — App Transport Security (ATS) misconfig + certificate-pinning bypass

阶段 4 — App Transport Security (ATS) 配置错误 + 证书固定绕过

Check for blanket ATS disablement (the single most common iOS network misconfig)

检查是否全面禁用了 ATS(iOS 网络配置错误中最常见的一种)

bash
plutil -extract NSAppTransportSecurity xml1 -o - Info.plist
Red flags in the output:
  • NSAllowsArbitraryLoads = true
    at the top level — HTTP (cleartext) allowed anywhere, app-wide.
  • Per-domain
    NSExceptionAllowsInsecureHTTPLoads = true
    for a domain that carries auth tokens.
  • NSAllowsArbitraryLoadsInWebContent = true
    — WKWebView traffic exempted, common blind spot.
A blanket ATS exception + a network position (rogue AP, ARP spoof, malicious VPN profile) = plaintext credential/token interception without touching pinning at all.
bash
plutil -extract NSAppTransportSecurity xml1 -o - Info.plist
输出中的危险信号:
  • 顶层
    NSAllowsArbitraryLoads = true
    ——允许应用范围内任意位置使用 HTTP(明文传输)
  • 对携带身份验证令牌的特定域设置
    NSExceptionAllowsInsecureHTTPLoads = true
  • NSAllowsArbitraryLoadsInWebContent = true
    ——豁免 WKWebView 流量,这是常见的盲区
全面 ATS 例外 + 网络位置(恶意 AP、ARP 欺骗、恶意 VPN 配置文件)= 无需触碰证书固定即可明文拦截凭据/令牌。

Certificate-pinning bypass (when pinning IS present and correctly configured)

证书固定绕过(当确实存在且配置正确的证书固定时)

bash
pip install --break-system-packages frida-tools objection
objection --gadget <bundle_id> explore
bash
pip install --break-system-packages frida-tools objection
objection --gadget <bundle_id> explore

inside objection:

inside objection:

ios sslpinning disable
If you want a Frida script instead, don't hand-roll one — use a maintained universal bypass
(e.g. the widely-used `frida-ios-pinning`/`ios-ssl-bypass` community scripts). Modern iOS TLS goes
through **BoringSSL**, so a reliable universal hook targets `SSL_CTX_set_custom_verify` /
`SSL_get_psk_identity` at the native layer and forces the verify callback to return "OK" — this
catches `URLSession`, `AFNetworking`, `Alamofire`, and `TrustKit` at once, which per-delegate
Objective-C hooks (like the deprecated `NSURLConnection` delegate) miss:
```bash
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`,而按 delegate 处理的 Objective-C hook(例如已弃用的 `NSURLConnection` delegate)会遗漏这些调用:
```bash

Pull a maintained universal BoringSSL-layer bypass and run it:

Pull a maintained universal BoringSSL-layer bypass and run it:

frida -U -f <bundle_id> -l ios-ssl-bypass.js --no-pause
In practice, prefer **SSL Kill Switch 2** (jailbroken device, installs as a tweak) or
**objection's `ios sslpinning disable`** over any hand-rolled script — both cover the common
pinning implementations (`NSURLSession`, `AFNetworking`, `TrustKit`) without per-app tuning.

---
frida -U -f <bundle_id> -l ios-ssl-bypass.js --no-pause
实际应用中,相较于自行编写的脚本,应优先使用 **SSL Kill Switch 2**(越狱设备,以 tweak 形式安装)或 **objection 的 `ios sslpinning disable`**——两者均可覆盖常见的证书固定实现(`NSURLSession`、`AFNetworking`、`TrustKit`),无需针对每个应用进行调整。

---

Stage 5 — URL scheme / Universal Link enumeration

阶段 5 — URL scheme / Universal Link 枚举

bash
undefined
bash
undefined

Custom URL schemes (CFBundleURLTypes) — anything can invoke these via Safari/another app

Custom URL schemes (CFBundleURLTypes) — anything can invoke these via Safari/another app

plutil -extract CFBundleURLTypes xml1 -o - Info.plist
plutil -extract CFBundleURLTypes xml1 -o - Info.plist

Universal Links / Associated Domains (applinks:) — requires a matching apple-app-site-association

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

For each custom scheme found (e.g. `myapp://`):
- Trigger it from Safari/Notes and observe what the app does with parameters:
  `myapp://reset-password?token=x&redirect=https://evil.com` — does the app trust an
  attacker-supplied `redirect`/`url`/`callback` param and load it in a WebView (open-redirect →
  WebView-XSS chain) or use it to bypass an auth screen?
- If the scheme is also registered by another app on the device (scheme squatting), a malicious
  app can intercept traffic intended for the legitimate app — check `CFBundleURLName` uniqueness.
- Universal Links degrade to the custom scheme when the AASA validation fails or is absent —
  test both paths for the same parameter-injection surface.

---
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/备忘录中触发它,并观察应用如何处理参数:
  `myapp://reset-password?token=x&redirect=https://evil.com`——该应用是否信任攻击者提供的 `redirect`/`url`/`callback` 参数并在 WebView 中加载它(开放重定向 → WebView-XSS 链),或利用它绕过身份验证界面?
- 如果同一 scheme 也由设备上的另一个应用注册(scheme 抢注),恶意应用可以拦截原本发往合法应用的流量——检查 `CFBundleURLName` 的唯一性。
- 当 AASA 验证失败或不存在时,Universal Link 会降级为自定义 scheme——针对同一参数注入面测试这两条路径。

---

Stage 6 — Runtime instrumentation (Frida / objection)

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

Requires a jailbroken device (checkra1n/palera1n for older iOS, or a Corellium virtual device) — unlike Android, there is no practical rooted-emulator equivalent for iOS.
bash
undefined
需要越狱设备(旧版 iOS 可使用 checkra1n/palera1n,或使用 Corellium 虚拟设备)——与 Android 不同,iOS 没有实用的已 root 模拟器等价方案。
bash
undefined

Setup

Setup

pip install --break-system-packages frida-tools objection
pip install --break-system-packages frida-tools objection

Install frida-server on the jailbroken device via Cydia/Sileo (frida repo), matching the

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.

host frida-tools version exactly — version skew is the #1 cause of "failed to attach" errors.

Full interactive exploration

—
objection --gadget <bundle_id> explore
undefined

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
undefined
bash
undefined

Network traffic capture (once pinning is bypassed)

Full interactive exploration

bash
mitmproxy --listen-port 8080
objection --gadget <bundle_id> explore

Set the device Wi-Fi proxy to host:8080, install the mitmproxy CA via http://mitm.it on-device

Inside objection:

(Settings > General > VPN & Device Management > trust the cert, then enable full trust under

—

Certificate Trust Settings — iOS requires this second step, unlike Android)

—

---
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
undefined

Decision tree — what to do with what you find

网络流量抓包(绕过证书固定后)

FindingNext move
NSAllowsArbitraryLoads = true
Confirm a token/credential actually transits HTTP — needs a network position to exploit, but is a real finding on its own (config-level, no MITM needed to report)
Hardcoded JWT / API key in strings dumpSame as Android — test against the API host, chain into
hunt-api-misconfig
GoogleService-Info.plist presentTest public Firestore/RTDB/Storage read (identical to apk-redteam-pipeline Stage 6)
Custom URL scheme accepts a
redirect
/
url
param
Test open-redirect → WebView-load chain; check for scheme squatting by other installed apps
Universal Link AASA missing/misconfiguredConfirm scheme fallback still carries the same injectable params
Entitlements show
keychain-access-groups
shared with other apps
Cross-app Keychain read — a compromised sibling app reads this app's secrets
Older API version referenced vs. what the current web app callsHand off to
hunt-shadow-api
for version-diffing

bash
mitmproxy --listen-port 8080

Anti-patterns

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)

  • Don't assume App Store = FairPlay-encrypted requires jailbreak — TestFlight and enterprise/ad-hoc builds are frequently NOT encrypted and need no decryption step at all. Always check distribution channel before reaching for
    frida-ios-dump
    .
  • Don't skip Swift binaries because class-dump shows nothing —
    strings
    and
    nm
    still work; a proper Swift-aware disassembler (Hopper, Ghidra with Swift demangling) recovers the rest.
  • Don't stop at "pinning is present" as a finding — pinning is a mitigation, not a vulnerability; the finding is what you can do once it's bypassed (or the ATS misconfig that makes it moot).
  • Don't ignore WKWebView-loaded content —
    NSAllowsArbitraryLoadsInWebContent
    is a distinct, frequently-overlooked exception from the top-level ATS setting.
  • Don't run Frida instrumentation against a personal/production Apple ID device — use a dedicated jailbroken test device or Corellium instance.


---

Tooling install (one-time)

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

bash
brew install libimobiledevice ideviceinstaller class-dump
pip install --break-system-packages frida-tools objection iphone_backup_decrypt
发现后续行动
NSAllowsArbitraryLoads = true
确认令牌/凭据是否确实通过 HTTP 传输——利用时需要网络位置,但该问题本身就是一个有效发现(配置层面,报告时无需 MITM)
strings 转储中存在硬编码 JWT/API key与 Android 相同——针对 API 主机进行测试,并接入
hunt-api-misconfig
存在 GoogleService-Info.plist测试公开的 Firestore/RTDB/Storage 读取(与 apk-redteam-pipeline 阶段 6 相同)
自定义 URL scheme 接受
redirect
/
url
参数
测试开放重定向 → WebView 加载链;检查其他已安装应用是否存在 scheme 抢注
Universal Link AASA 缺失或配置错误确认 scheme 降级路径是否仍会传递相同的可注入参数
Entitlements 显示
keychain-access-groups
与其他应用共享
跨应用 Keychain 读取——被攻陷的兄弟应用可读取此应用的机密
引用的 API 版本低于当前 Web 应用使用的版本移交给
hunt-shadow-api
进行版本差异分析

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

—

---
  • 不要想当然地认为 App Store 构建需要越狱来解密 FairPlay 加密——TestFlight 和企业/ad-hoc 构建通常未加密,完全不需要解密步骤。判断是否需要
    frida-ios-dump
    前,务必先确认分发渠道。
  • 不要因为 class-dump 没有输出就跳过 Swift 二进制文件——
    strings
    和
    nm
    仍然有效;支持 Swift 的专业反汇编器(Hopper、Ghidra 配合 Swift demangling)可以恢复其余内容。
  • 不要把“存在证书固定”本身当作发现——证书固定是一种缓解措施,而不是漏洞;真正的发现是绕过它后能够执行的操作(或使它失效的 ATS 配置错误)。
  • 不要忽略 WKWebView 加载的内容——
    NSAllowsArbitraryLoadsInWebContent
    是独立于顶层 ATS 设置的例外项,而且经常被忽略。
  • 不要在个人/生产环境 Apple ID 设备上运行 Frida 插桩——请使用专用的越狱测试设备或 Corellium 实例。

Related Skills & Chains

工具安装(一次性)

  • apk-redteam-pipeline
    — the Android counterpart; run both when a target ships on both platforms. Sibling bundle IDs and shared backend endpoints frequently surface cross-platform.
  • hunt-shadow-api
    — mobile builds (iOS and Android alike) often hardcode an older API version than the current web app. Chain: IPA reveals
    /v1/*
    endpoints →
    hunt-shadow-api
    diffs
    /v1/
    against the current
    /v3/
    for auth/validation regressions.
  • cloud-iam-deep
    — IPA secret extraction frequently yields live AWS/GCP/Azure credentials or Firebase configs. Chain: strings-grep produces an AWS key →
    cloud-iam-deep
    privilege analysis.
  • hunt-api-misconfig
    — hardcoded JWTs/API keys extracted here feed directly into JWT algorithm-confusion and mass-assignment testing there.
  • evidence-hygiene
    — extracted Keychain items and secrets need redaction before report inclusion.
  • offensive-osint
    — App Store developer-page enumeration is part of the broader org recon graph; pair with certificate-transparency lookups for the same brand.
bash
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

—

---
—

相关 skill 与链路

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