BIPI
BIPI

iOS App Pentesting: IPA Decryption, Frida, and Keychain Extraction

Cybersecurity

iOS testing requires a jailbroken device, frida, and a willingness to read Objective-C. The platform is not magic; it is just well-defended defaults that get bypassed by misuse.

By Arjun Raghavan, Security & Systems Lead, BIPI · March 9, 2025 · 8 min read

#ios#mobile#pentest

iOS apps ship encrypted to the App Store. To analyze them statically you need a jailbroken device to dump the decrypted Mach-O. From there the workflow mirrors Android: read the binary, instrument the runtime, abuse exposed interfaces. The findings are different because iOS provides stronger defaults; the wins come from misuse of those defaults.

Methodology: getting the binary

Install the target app on a jailbroken device (palera1n on A11 and earlier, Dopamine on A12+ for iOS 15-16). Use frida-ios-dump or bagbak to pull a decrypted IPA. Open it in Hopper or Ghidra for static review. otool -L gives linked frameworks; otool -hv shows PIE and other binary protections; class-dump pulls Objective-C class definitions if the app is not pure Swift.

  • frida-ios-dump -l: list installed apps; -f bundleid pulls the decrypted IPA.
  • otool -hv binary: confirm PIE, NX, ARC. Older builds without PIE are an immediate finding.
  • class-dump -H App.app/App -o headers/: extract Objective-C interface definitions.
  • objection -g com.target.app explore: interactive runtime introspection.
  • ios keychain dump: pull every keychain item the app can access.

Keychain, plist, and URL schemes

Three iOS-specific finding categories show up over and over. Keychain items stored with kSecAttrAccessibleAlways instead of kSecAttrAccessibleWhenUnlockedThisDeviceOnly are accessible from a backup. plist files in the app bundle leak hardcoded API keys, internal URLs, and feature flags. Custom URL schemes (myapp://action?param=value) are the iOS equivalent of Android deep links and have the same handler-validation issues.

Frida bypasses for SSL pinning and jailbreak detection

objection's ios sslpinning disable handles NSURLSession, AFNetworking, and Alamofire by default. For TrustKit or custom NSURLSessionDelegate implementations, hook URLSession:didReceiveChallenge: and force completionHandler with NSURLSessionAuthChallengePerformDefaultHandling. Jailbreak detection in iOS apps is almost always defeatable: they check for /Applications/Cydia.app, fork(), or stat() on known files. objection ios jailbreak disable hooks the common functions.

Detection

Use App Attest to bind requests to a specific app instance and DeviceCheck for per-device server-side flags. Server-side, alert on attestation failures and on requests missing the expected client signature. Frida's frida-server runs on port 27042 by default; the app can probe that port at startup but a tampered app will skip the check.

Remediation

  1. Store secrets in Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly and kSecAttrSynchronizable=false unless sync is required.
  2. Never put API keys, internal URLs, or feature flags in plist files inside the app bundle. Fetch them server-side after authentication.
  3. Validate URL scheme parameters server-side. Treat custom URL scheme inputs as untrusted. Prefer Universal Links, which require associated-domain verification.
  4. Enforce App Transport Security (ATS). Do not add NSAllowsArbitraryLoads exceptions in production.
  5. Implement App Attest for high-value endpoints. The attestation token validates the app binary and device.
  6. Pin certificates with TrustKit or a vetted custom NSURLSessionDelegate. Include a backup pin.
  7. Use frida-detection libraries as a tripwire (not a control). Log attestation failures and frida-port hits for fraud teams to triage.

Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.