Mobile Penetration Testing Methodology — iOS and Android
Published May 3, 2026 · 18 min read · VAPT
Mobile pentests look superficially like web pentests — an HTTP API at the bottom, a UI at the top — but the interesting bugs live in places web testers do not normally touch: keychains and Keystores, deep links and intent filters, certificate pinning, biometric prompts, local SQLite stores, runtime code that can be hooked. This methodology walks an iOS + Android engagement end-to-end, mapped to the OWASP Mobile Application Security project and the MASVS control set (L1, L2, R).
Scope and rules of engagement
- App package — signed release IPA (iOS) and APK or AAB (Android), with the exact version under test.
- Test accounts in two tenants and two roles (mandatory for authorisation testing).
- Backend API endpoints — production or pre-prod; aligned with the API pentest scope if joint engagement.
- Jailbroken iPhone (or corellium) and rooted Android (or genymotion / android-studio emulator with magisk).
- Out-of-scope: certificate pinning issues that depend on a jailbroken device alone (those need additional context to be material).
MASVS — verification levels
OWASP MASVS defines three levels: L1(standard security — any mobile app),L2(defence in depth — apps handling sensitive data or regulated PII), andR(resilience against reverse engineering — apps with IP, anti-cheat or anti-fraud requirements). Scope the engagement against the level the app is supposed to meet and report against that bar — do not flag missing R controls on an L1 app.
| MASVS Group | Coverage |
|---|---|
| MASVS-STORAGE | Sensitive data at rest — Keychain, Keystore, files |
| MASVS-CRYPTO | Cryptographic primitives, key management |
| MASVS-AUTH | Authentication, session, biometric |
| MASVS-NETWORK | TLS, pinning, hostname validation |
| MASVS-PLATFORM | IPC, deep links, intents, WebView |
| MASVS-CODE | Code quality, dependency hygiene, hardening |
| MASVS-RESILIENCE | Anti-tamper, anti-debug, integrity (level R) |
| MASVS-PRIVACY | User-visible privacy controls and consent |
Tooling matrix
| Tool | Platform | Use |
|---|---|---|
| MobSF | iOS + Android | Static + dynamic analysis, automated triage |
| JADX | Android | DEX-to-Java decompiler — the standard Android source viewer |
| apktool | Android | APK unpack/repack, smali editing |
| class-dump | iOS | Objective-C class hierarchy from Mach-O |
| Frida | iOS + Android | Dynamic instrumentation, hooks, runtime patching |
| Objection | iOS + Android | Frida-powered runtime exploration without writing scripts |
| Drozer | Android | IPC and content provider security framework |
| Burp / mitmproxy | iOS + Android | HTTPS interception with installed root CA |
Phase 1 — static analysis
Static is cheap and high-yield. Run MobSF first for the automated triage report; review JADX manually for everything MobSF does not parse.
Android static
- Decompile with JADX — review for hardcoded secrets, API keys, URLs, weak crypto.
- Inspect
AndroidManifest.xml— exported activities, services, content providers, broadcast receivers;android:allowBackup;android:debuggable; deep-link intent filters. - Network security config —
res/xml/network_security_config.xml; cleartext traffic permitted; trust anchors. - Native libraries —
lib/*/*.so; review for JNI side-channel and pinned libraries used in obfuscation.
iOS static
- Run
class-dumpagainst the Mach-O binary for Objective-C; for Swift useotool -land the ipsw / ground-truth tooling. - Inspect
Info.plist— URL schemes, App Transport Security exceptions, background modes. - Embedded resources — strings in the binary often leak API keys;
strings -a App.app/App | grep -E '(api|key|token)'. - Provisioning profile + entitlements —
codesign -d --entitlements :- App.app.
# Android: MobSF static scan
docker run -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
# upload APK in browser, review report
# Android: JADX from CLI
jadx -d out target.apk
grep -RInE "(api[_-]?key|secret|password|aws_access)" out/
# Android: manifest extraction
apktool d -s -o target-out target.apk
cat target-out/AndroidManifest.xml | grep -E "exported|debuggable|allowBackup"
# iOS: class-dump (after decryption with frida-ios-dump)
class-dump -H App.app/App -o headers/
strings -a App.app/App | grep -iE "(api[_-]?key|secret|token|http)"
codesign -d --entitlements :- App.app/AppPhase 2 — dynamic analysis and traffic interception
Dynamic analysis means running the app on a real (or emulated) jailbroken/rooted device with traffic intercepted through Burp or mitmproxy.
- Install Burp's CA in the system store on Android (after API 24, user-installed CAs are not trusted by default — this requires either a system-trusted install on a rooted device or a network-security-config exemption).
- On iOS, install the Burp profile and trust it under Settings → General → About → Certificate Trust Settings.
- Confirm traffic flows through Burp on a non-pinned endpoint before assuming pinning is the cause of empty traffic.
- For pinned apps, bypass with Frida hooks (Objection's built-in is a one-liner, see below).
Phase 3 — certificate pinning bypass
Pinning is implemented in many ways: OkHttp CertificatePinner, Network Security Config XML, custom X509TrustManager, native pinning with BoringSSL or OpenSSL. The Frida ecosystem has stable bypass scripts for the common patterns; for custom pinning, you write a hook against the verification function.
# Android: Objection one-liner
objection -g com.target.app explore
android sslpinning disable
# Android: Frida with the Universal Android SSL Pinning Bypass script
frida -U -l https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida/ \
-f com.target.app
# iOS: Objection
objection -g TargetApp explore
ios sslpinning disable
# iOS: ssl-kill-switch3 (replacement for the deprecated kill-switch-2)
# https://github.com/nabla-c0d3/ssl-kill-switch2Phase 4 — secure storage validation
Sensitive data should sit in the platform's secure storage, not in NSUserDefaults,SharedPreferences, plain SQLite or the filesystem.
- iOS — Keychain with the appropriate accessibility class (
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,...WhenUnlockedThisDeviceOnlyfor sensitive items). Anything inNSUserDefaultsor~/Documentsis fair game in the report. - Android — AndroidKeyStore for keys, EncryptedSharedPreferences (Jetpack Security) for KV. SQLite without SQLCipher and unencrypted Realm databases are findings.
- Backup posture — Android
android:allowBackup="true"can leak data viaadb backup; iCloud / iTunes backup of sensitive Keychain items happens unless the accessibility class includesThisDeviceOnly. - Reference: Apple Platform Security guide; Android security best practices.
# Objection: dump iOS keychain
ios keychain dump
# Objection: enumerate Android shared preferences
android hooking list shared_preferences
android shared_preferences get com.target.app target_prefs
# Pull SQLite from Android sandbox (rooted)
adb shell run-as com.target.app cat databases/target.db > target.db
sqlite3 target.db ".tables"Phase 5 — biometric and authentication bypass
Biometric prompts (Touch ID, Face ID, Android BiometricPrompt) gate access to sensitive flows. Common bugs:
- Biometric result evaluated client-side only — success boolean replaced via Frida hook.
- Token issued before biometric success and only displayed after — Frida-dump the in-memory token.
- Fallback to passcode permitted when policy says no.
- Jailbreak-detection bypass — same Frida pattern, hook the detection routine to return clean.
# Frida: hook Android BiometricPrompt result
Java.perform(function() {
var Cb = Java.use("androidx.biometric.BiometricPrompt$AuthenticationCallback");
Cb.onAuthenticationSucceeded.implementation = function(r) {
console.log("[+] Forcing biometric success");
return this.onAuthenticationSucceeded(r);
};
});
# Objection iOS LocalAuthentication bypass
ios ui biometrics_bypassPhase 6 — deep-link and IPC attacks
On Android, exported activities, intent filters, content providers and broadcast receivers form a rich IPC attack surface. On iOS, custom URL schemes and Universal Links are the equivalent.
- Drozer —
run app.package.attacksurface com.target.appenumerates the attack surface;run app.activity.start --component com.target.app com.target.app.AdminActivitystarts an exported activity directly. - Content provider URI traversal —
content://com.target.app.provider/../../../data/data/com.target.app/databases/target.dbpatterns. - Custom URL scheme parameter injection —
targetapp://login?next=https://attacker.exampleredirect chains. - Universal Link / App Link mis-association — missing
apple-app-site-associationorassetlinks.jsonletting another app capture the link. - WebView
javascript:URL handling — deep links that open a WebView with attacker-controlled URL.
# Android: launch exported activity directly
adb shell am start -n com.target.app/.AdminActivity
# Android: deep-link probe with extras
adb shell am start -W -a android.intent.action.VIEW \
-d "targetapp://reset?token=anything&user=victim" com.target.app
# iOS: simulator URL scheme
xcrun simctl openurl booted "targetapp://login?next=https://attacker.example"
# Drozer attack-surface
drozer console connect
> run app.package.attacksurface com.target.app
> run app.provider.finduri com.target.app
> run scanner.provider.traversal -a com.target.appPhase 7 — runtime instrumentation patterns
Frida is the workhorse. Common runtime patterns the operator should know cold:
- Hook a Java method —
Java.use("com.target.X").method.implementation = function() {...}. - Hook an Objective-C method —
Interceptor.attach(ObjC.classes.X["- selector:"].implementation, ...). - Trace native calls —
frida-trace -U -i "CC*" -f com.target.appfor CommonCrypto. - Memory-scan for tokens —
Memory.scanSync(...)across the heap. - Defeat root/jailbreak detection — hook the detection function, return clean.
Phase 8 — backend API testing in context
A mobile pentest is incomplete without exercising the backend API. The mobile client's traffic, captured through the proxy, is a high-fidelity source of endpoint discovery. Replay those endpoints with a different account's token (BOLA), with privileged fields added to JSON bodies (mass assignment), without the auth token (anonymous fallback), with manipulated headers (X-Forwarded-For, X-Mobile-Device-ID). Many backend bugs are only reachable through the mobile API surface because the web client never talks to those endpoints in the same shape. Cross-reference findings with the OWASP API Security Top 10.
Phase 9 — resilience controls (level R)
Apps that need to resist reverse engineering — payments, anti-cheat games, DRM, anti-fraud wallets — should also implement the MASVS-RESILIENCE controls. Verify:
- Anti-debug — detection of
ptrace,frida-server, debugger ports; reaction (close app, alert backend) on detection. - Root / jailbreak detection — multiple independent checks across native + Java/Swift code so a single Frida hook cannot bypass all of them.
- Integrity — signing certificate hash check at startup; backend attestation via Play Integrity or Apple App Attest.
- Code obfuscation — ProGuard / R8 for Android; Swift / Obj-C symbol stripping for iOS; control-flow obfuscation for high-value routines.
- Anti-tampering — runtime checksum of the loaded binary; refusal to start if the package signer differs from the embedded fingerprint.
The deliverable for level R explicitly catalogues which Frida hooks are required to bypass the app, how long the bypass took, and which of the customer's controls fired during the exercise.
Reporting
Map every finding to a MASVS control. Distinguish L1 vs. L2 vs. R applicability so the customer sees the bar they should be measured against. Include reproduction steps that work on the version under test — iOS / Android churn the platform APIs each year, so reports should pin tool versions and OS levels.
References: OWASP MASTG (Mobile App Security Testing Guide), OWASP MAS project, MobSF, Frida.
For a scoped iOS/Android pentest aligned with this methodology, see the AxVeil VAPT service.
Plan your mobile pentest with AxVeil.
iOS and Android coverage. MASVS L1/L2/R alignment, pinning bypass, secure storage, biometric bypass, deep-link and IPC attacks, retest included.
Talk to a senior operator about mobile pentest scope →