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 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
- Store secrets in Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly and kSecAttrSynchronizable=false unless sync is required.
- Never put API keys, internal URLs, or feature flags in plist files inside the app bundle. Fetch them server-side after authentication.
- Validate URL scheme parameters server-side. Treat custom URL scheme inputs as untrusted. Prefer Universal Links, which require associated-domain verification.
- Enforce App Transport Security (ATS). Do not add NSAllowsArbitraryLoads exceptions in production.
- Implement App Attest for high-value endpoints. The attestation token validates the app binary and device.
- Pin certificates with TrustKit or a vetted custom NSURLSessionDelegate. Include a backup pin.
- 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.