ofensiva
iOS
mobile pentesting
Frida

iOS app pentesting: jailbreak, Frida and MASVS L1-L2 2026

iOS app pentesting: jailbreak detection bypass, Frida hooking, MASVS L1/L2, keychain abuse, IPA reverse engineering and app transport security.

SecraJune 8, 202615 min read

Auditing an iOS app is nothing like auditing an Android app, even though both are mobile. Apple's closed ecosystem, mandatory binary signing, the strict XNU kernel sandbox and the operational dependence on the App Store impose constraints that completely change the toolchain and the order of tests. A proper iOS pentest requires a physical device with jailbreak, cannot be solved with a simulator and demands specific techniques such as dynamic hooking of Objective-C and Swift methods with Frida or runtime certificate pinning bypass.

This guide describes how to build the lab, what MASVS L1 and L2 cover, the vectors that show up repeatedly in real reports and the countermeasures that actually close the door. It is aimed at security teams, iOS developers who want to understand what will be evaluated against their app and decision makers who need to define the scope of a mobile audit.

The essentials: iOS pentesting requires a physical device with jailbreak (checkra1n, palera1n or Dopamine depending on version), Frida for dynamic analysis and Objection to automate common tasks. MASVS L1 covers general apps, L2 adds controls for apps handling sensitive or financial data. Recurring findings are misconfigured keychain, hardcoded secrets in Info.plist or binary, insecure UserDefaults storage, sensitive logging, missing or trivially bypassed pinning and unvalidated deeplinks. Effective hardening combines kSecAttrAccessibleWhenUnlocked, strict ATS, multilayer jailbreak detection and LLVM-level obfuscation.

Why iOS pentest needs a specific setup

iOS ships with three defensive layers that do not exist in traditional Android. The first is the per-app sandbox, isolating each binary in /var/mobile/Containers/Data/Application/{UUID} with no access to the rest of the system. The second is mandatory code signing: any binary not signed by Apple or a valid developer certificate is rejected at load time. The third is full filesystem encryption tied to hardware (Secure Enclave) preventing readable disk access without first decrypting each file's key.

These three layers make any analysis without jailbreak shallow. With no root access you cannot read the decrypted binary, cannot inspect the keychain, cannot modify the ramdisk to inject agents and cannot bypass the protections the app itself implements. The Xcode simulator does not help either: it runs x86_64 or arm64 binaries compiled for macOS, not actual ARM iOS, and many sensitive APIs (real keychain, Secure Enclave, biometric sensors) are emulations that do not match real behavior.

The practical conclusion is direct: for a serious iOS pentest you need a physical iPhone or iPad, jailbroken, dedicated to the lab. Buying a second hand device compatible with the iOS version you want to audit is the first cost of the project.

iOS lab setup

The minimum stack we use in real audits combines host software with tools running on the target device.

On the host (macOS preferred, Linux usable with limitations):

  • Xcode with its Command Line Tools for lldb, otool, codesign and xcrun. Needed even if you do not develop, because many utilities depend on its toolchain.
  • MobSF (Mobile Security Framework) for automated static analysis of IPAs. Generates an initial report on strings, permissions, ATS and detection of known insecure patterns.
  • Frida and its CLI (frida, frida-trace, frida-ps). Dynamic hooking, function interception and runtime manipulation.
  • Objection on top of Frida. Automates common tasks: keychain dump, pinning bypass via preinstalled scripts, sandbox filesystem exploration.
  • Hopper or Ghidra for Mach-O reversing. Ghidra is free and enough for most cases.
  • class-dump to extract the Objective-C class hierarchy from the binary and understand what classes and methods are exposed.
  • Burp Suite or mitmproxy as HTTP/S interception proxy.

On the jailbroken device:

  • checkra1n for devices up to iPhone X with iOS 12 to 14 (permanent jailbreak based on the checkm8 bootrom exploit).
  • palera1n for iPhone X and earlier with iOS 15, 16 and 17 (also based on checkm8, semi-tethered jailbreak).
  • Dopamine for arm64e devices (iPhone XS and later) with iOS 15 to 17 (semi-untethered jailbreak based on kernel exploits).
  • Frida server installed via Cydia/Sileo from the official Frida repo.
  • OpenSSH to connect to the device by SSH (root with default password alpine, change it immediately).
  • Filza or equivalent file manager to navigate the filesystem from the device itself.

Mac-iPhone pairing happens over USB with idevicepair pair or by opening an SSH session to root@<iphone-ip> after installing OpenSSH. The first action is always to change the default password: leaving alpine on a jailbroken device connected to a network exposes it to historical worms such as Ikee.

OWASP MASVS L1 vs L2

The reference standard is MASVS (Mobile Application Security Verification Standard) along with its operational companion MASTG (Mobile Application Security Testing Guide), both maintained by OWASP. MASVS defines security requirements across two levels plus an optional resilience layer.

L1 (Standard Security). Coverage for any mobile app. Verifies basic controls: encrypted communications, no plaintext storage of sensitive data, correct authentication, no unnecessary functionality exposure and acceptable log handling. The right level for apps not handling financial, health or critical infrastructure access.

L2 (Defense-in-Depth). Adds stricter controls for apps handling regulated sensitive data: banking, healthcare, government, identity. Reinforces authentication (multi-factor, correctly integrated biometrics), requires stronger encryption for local storage, forbids certain APIs (unrestricted clipboard, screenshots on sensitive screens), mandates certificate pinning and strict deeplink validation.

MASVS-R (Resilience). Optional layer on top of L1 or L2. Applied when the app must resist reverse engineering and tampering: detection and response to jailbreak, debugger, Frida hooks or emulation, runtime code integrity, obfuscation. Common in banking, gaming and DRM apps.

MASTG is the catalog of concrete tests. Each MASVS control maps to one or several documented test cases with commands, scripts and expected outcomes. It is the real operational reference when deciding how to validate a specific control.

Static IPA analysis

The IPA is a ZIP with .ipa extension. Inside there is a Payload/{AppName}.app/ directory with the Mach-O binary, nib/storyboardc files, Info.plist, resources and the _CodeSignature folder.

Typical static analysis steps:

  1. Obtain decrypted IPA. The App Store binary is encrypted with FairPlay. For real reversing it has to be extracted decrypted from the device. Tools like frida-ios-dump, bagbak or flexdecrypt do it in seconds on a jailbroken device.
  2. Unzip and analyze Info.plist. Convert from binary to XML with plutil -convert xml1 Info.plist. Look for suspicious entries: NSAppTransportSecurity with global exceptions, CFBundleURLTypes with poorly validated custom schemes, API keys embedded in custom strings.
  3. Inspect the Mach-O with otool. Check architectures (otool -h), linked dynamic libraries (otool -L), hardening flags (PIE, ARC, stack canaries via otool -hv).
  4. Objective-C class dump with class-dump {binary} > classes.h. Useful to understand the exposed surface before hooking.
  5. Strings with strings or rabin2. Search for URLs, internal endpoints, tokens, keywords (password, token, secret, api_key). Trivial to find hardcoded secrets this way.
  6. Deep reverse engineering in Hopper or Ghidra for critical functions: license validation, pinning logic, jailbreak checks.

A common pattern: development teams leave staging endpoints or cloud service tokens in Info.plist or as binary constants assuming "it is inside the app, no one will see it". With strings and grep they appear in seconds.

Dynamic analysis with Frida

Static analysis is necessary but rarely sufficient. Most critical findings come from runtime, where you observe what the app actually does for the user, what it calls, what it stores and what it sends.

Basic Frida workflow:

# List processes on the device
frida-ps -Uai

# Spawn the app with a script injected at launch
frida -U -f com.company.app -l script.js --no-pause

# Attach to a running app
frida -U -n AppName -l script.js

A typical script for tracing Objective-C calls:

if (ObjC.available) {
  Interceptor.attach(ObjC.classes.NSURLSession['- dataTaskWithRequest:completionHandler:'].implementation, {
    onEnter: function (args) {
      var req = new ObjC.Object(args[2]);
      console.log('[NSURLSession] ' + req.URL().absoluteString());
    }
  });
}

Swift hooking is more complex because names are mangled. Frida 16+ resolves Swift symbols via Swift.classes, but it is usually more practical to hook the underlying Objective-C functions (most sensitive SDK APIs are still Objective-C even when the app is written in Swift).

Certificate pinning bypass. The most recurring case. Objection ships with a ready command:

objection -g com.company.app explore
> ios sslpinning disable

Internally it hooks the validation functions in NSURLSession, AFNetworking, Alamofire and TrustKit, always returning success. If the app implements custom pinning (manually comparing hashes against the certificate), a specific hook has to be written.

Once pinning is disabled, configure the iPhone proxy toward Burp in the WiFi settings and install the Burp CA certificate on the device (Settings, General, About, Certificate Trust Settings, enable trust). From that point on, all HTTPS traffic from the app is observed and modified through Burp.

Common vulnerabilities in iOS apps

Findings repeating in report after report grouped by family.

Misconfigured keychain. The keychain is the secure iOS store for credentials and tokens. Each entry has a kSecAttrAccessible attribute defining when it is readable. Values like kSecAttrAccessibleAlways or kSecAttrAccessibleAlwaysThisDeviceOnly (deprecated but still seen) leave the secret accessible even with the device locked, allowing extraction after physical compromise. The correct value for sensitive data is kSecAttrAccessibleWhenUnlockedThisDeviceOnly.

Hardcoded secrets. API keys, Firebase tokens, cloud service credentials or connection strings buried in Info.plist, in additional .plist files or as binary strings. Extracted with strings or surfaced by MobSF. The typical pattern is to assume the IPA signature protects content, which is false: anyone with a Mac can decrypt and read it.

Insecure UserDefaults storage. UserDefaults is not an encrypted store, it is a .plist in Library/Preferences/. Storing session tokens, JSON Web Tokens or personal data there leaves them in plaintext and readable after jailbreak.

Sensitive logging. NSLog, os_log and print end up accessible in the system console (idevicesyslog from the host). Logging API response bodies, tokens in headers or authentication flows leaks credentials on any device connected via USB.

Weak biometric authentication. Implementing LAContext.evaluatePolicy without verifying specific LAError values or without binding to the keychain via kSecAccessControl allows trivial bypasses with Frida hooks returning success=true. The safe pattern ties the biometric operation to unlocking a keychain item with SecAccessControlCreateWithFlags and the .biometryCurrentSet flag.

Universal Links and unvalidated deeplinks. If the app opens URLs of its custom scheme (myapp://) without validating origin or payload signature, an attacker can force navigation to internal views, trigger authenticated actions (transfer, change password) or inject payloads into internal webviews.

WebView with exposed JavaScript bridge. WKWebView configured with WKUserContentController and handlers accepting unfiltered input allows execution of native functions from controlled JavaScript. If the WebView also loads remote content over HTTP or from uncontrolled origin, the MITM attacker gains execution over native APIs.

ATS exceptions. App Transport Security forces HTTPS with TLS 1.2 and modern ciphers by default. Exceptions (NSAllowsArbitraryLoads, NSExceptionDomains) are visible directly in Info.plist. A global exception opens the door to downgrade and MITM in hostile networks.

Trivial jailbreak detection. Checking /Applications/Cydia.app or /private/var/lib/apt is bypassed with a NSFileManager.fileExistsAtPath: hook returning false for those paths. Serious banking apps combine ten or fifteen checks at different levels (filesystem, sandbox escape, dyld, sysctl, fork) and respond non-deterministically.

Insecure IPC. Custom URL schemes registered without validating the caller origin, use of the general pasteboard for sensitive data between apps, app extensions with excessive permissions. Any installed app can read the general pasteboard; copying passwords or tokens there is a direct leak.

Typical Frida workflow in a real audit

The flow we repeat in every iOS engagement is ordered like this:

  1. Spawn the app with Frida attached and a generic logging script (all calls to NSURLSession, SecItemAdd, LAContext, WKWebView).
  2. Full functional run (login, navigation, transaction, logout). Frida logs what moves underneath.
  3. Keychain dump with objection > ios keychain dump. Inspection of what is stored and at which accessibility level.
  4. Sandbox filesystem listing with objection > env. Inspection of Documents/, Library/Caches/, Library/Preferences/, tmp/.
  5. Pinning bypass with ios sslpinning disable and traffic capture in Burp.
  6. Targeted reverse engineering of critical functions (license validation, anti-debug logic, JB checks) with Ghidra and specific Frida hooks to nullify them.
  7. IPC testing by launching custom URLs (xcrun simctl openurl in simulator, uiopen on device) and app extensions from other test apps.
  8. Behavior analysis across states (with network, without network, fresh account, privileged account).

Each finding is documented with screenshot, request/response and, where applicable, a reproducible Frida script.

Effective hardening

The countermeasures that actually close the door, ordered by impact:

  • Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly and SecAccessControl with biometryCurrentSet for sensitive items. Blocks offline extraction and binds usage to an unlocked session with current biometrics.
  • Strict ATS with no exceptions. If communication with legacy domains is needed, change the backend rather than open a hole. Any ATS exception is technical debt that shows up in the report.
  • Pinning with a custom URLSessionDelegate validating Subject Public Key Info hash, not the full certificate. On standard URLSession or on TrustKit correctly configured.
  • Multilayer jailbreak detection: checks across filesystem, dyld, sandbox, fork, sysctl, integrity of critical functions, all compiled in C, not in hookable Objective-C. Non-deterministic response (do not exit immediately: degrade functionality so the attacker cannot locate the check via bisect).
  • LLVM-level obfuscation with passes such as Hikari, Obfuscator-LLVM or commercial equivalents. Makes reverse engineering take days instead of hours for critical functions.
  • Runtime integrity checks: hash of __TEXT sections of the binary against expected value, Frida detection via /proc/self/maps (sysctl on iOS) or probing common frida-server ports.
  • Do not log sensitive data. Logging policy forbidding response bodies, tokens, auth headers and personal data at any level.
  • Strict URL and deeplink validation with domain allowlist and signing of sensitive payloads.

No isolated control is enough. The stack is evaluated as a whole.

App Store, MDM and enterprise distribution

Distribution context matters. A public App Store app passes Apple's strict filters (human review, automated scans) but is not immune: critical findings appear anyway. Enterprise apps distributed via Apple Business Manager and signed with an enterprise developer certificate skip review, which increases the risk of oversight.

MDM (Mobile Device Management) solutions enable policies that close many vectors: jailbreak blocking, prohibition of unsigned app installation, separation of personal and corporate containers, remote wipe. Auditing an app distributed only via MDM requires replicating the policy on the lab device.

Sideloading via enterprise certificate is a known risk. Apple revokes certificates it detects being abused, but between revocations malicious apps are distributed signed as legitimate ones. Any app appearing installed outside the App Store on a corporate device is a signal for immediate investigation.

Frequently asked questions

Can iOS pentest be done without jailbreak

Static analysis yes (on an extracted or downloaded IPA). Real dynamic analysis no. Without jailbreak there is no Frida server, no keychain access, no sandbox readback and no way to inspect what is stored on disk. An audit without jailbreak catches at best 30 to 40 percent of the findings a full audit catches.

Is the Xcode simulator enough for auditing

No. The simulator runs host architecture (x86_64 or arm64 macOS), not real ARM iOS, and many sensitive APIs are emulations. Keychain, Secure Enclave, biometrics and sandbox behaviors are not real. It works for development and as complementary static analysis, not as a substitute for the physical device.

Does Apple reject apps for security findings in review

Apple mainly reviews UX guideline compliance, declared privacy (App Privacy Report) and forbidden APIs. It does not perform pentest. It rejects apps using private APIs, lying in the privacy manifest or violating obvious policies, but a hardcoded secret or a misconfigured keychain passes review without issue.

MASVS L1 or L2, which to choose for an audit

L1 is the reasonable minimum for any app. For apps handling sensitive personal data, payments, health, government or identity, L2 is the expected baseline. Apps with relevant reverse engineering risk (banking, gaming with purchases, DRM) add MASVS-R on top of the base level. The decision is usually driven by the sector regulator when applicable.

On your own app or on apps with the owner's authorization, yes. On third party apps without authorization it falls into a grey zone depending on jurisdiction and purpose. In professional audits the scope is always signed and the client explicitly authorizes dynamic analysis, reversing and security testing on the target app.

How long does an iOS audit take

An L1 audit on a medium complexity app (10 to 20 screens, login and standard functionality) takes 5 to 8 effective working days. L2 on a financial app with complex backend and added resilience (MASVS-R) goes up to 10 to 15 days. The differentiators are number of endpoints, authentication flow complexity and depth of reversing required.

iOS pentest with Secra

At Secra we execute full iOS audits over MASVS L1 and L2 with an optional MASVS-R extension. We combine static analysis of the IPA, dynamic analysis with Frida and Objection, targeted Ghidra reversing and review of the backend integration. The deliverable includes prioritized findings, reproducible technical evidence and hardening recommendations specific to each control. If your app ships through App Store, MDM or both, we cover it in the same project.

Contact our team to define scope and timelines for the iOS audit of your application.

About the author

Secra Solutions team

Ethical hackers with OSCP, OSEP, OSWE, CRTO, CRTL and CARTE certifications, 7+ years of experience in offensive cybersecurity, and authors of CVE-2025-40652 and CVE-2023-3512.

Share article