Strobesstrobes
Platform
Solutions
Resources
Customers
Company
Pricing
Book a Demo
Strobesstrobes

Strobes connects every exposure signal to autonomous action, so security teams fix what matters, prove what works, and stop chasing noise.

Book a DemoTalk to an expert
ISO 27001SOC 2CREST
  • Platform
  • Platform Overview
  • Agentic Exposure Management
  • AI Agents
  • Integrations
  • API & Developers
  • Workflows & Automation
  • Analytics & Reporting
  • Solutions
  • Exposure Assessment (EAP)
  • Attack Surface Management
  • Application Security Posture
  • Risk-Based Vulnerability Management
  • Adversarial Exposure Validation (AEV)
  • AI Pentesting
  • Pentesting as a Service
  • CTEM Framework
  • By Industry
  • Financial Institutions
  • Technology
  • Retail
  • Healthcare
  • Manufacturing
  • By Roles
  • CISOs
  • Security Directors
  • Cloud Security Leaders
  • App Sec Leaders
  • Resources
  • Quick Agentic Pentest
  • Blog
  • Customer Stories
  • eBooks
  • Datasheets
  • Videos & Demos
  • Exposure Management Academy
  • CTEM Maturity Assessment
  • Pentest Health Check
  • Security Tool ROI Calculator
  • Company
  • About Strobes
  • Meet the Team
  • Trust & Security
  • Contact Us
  • Careers
  • Become a Partner
  • Technology Partner
  • Partner Deal Registration
  • Press Release

Weekly insight for security leaders

CTEM research, agentic AI trends, and what's actually moving the needle.

© 2026 Strobes Security Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyAccessibilitySitemap
Back to Blog
What Is Mobile App Penetration Testing? (iOS and Android)
Application SecurityPenetration Testing

What Is Mobile App Penetration Testing? (iOS and Android)

Shubham JhaApril 25, 20257 min read

Table of Contents

  • What is mobile app penetration testing?
  • Where do you start when you unpack the binary?
  • Static analysis only tells you what is possible
  • How does dynamic analysis confirm a finding?
  • How is iOS pentesting different from Android?
  • A WebView that no one pinned
  • What do the fixes actually look like?
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

Table of Contents

  • What is mobile app penetration testing?
  • Where do you start when you unpack the binary?
  • Static analysis only tells you what is possible
  • How does dynamic analysis confirm a finding?
  • How is iOS pentesting different from Android?
  • A WebView that no one pinned
  • What do the fixes actually look like?
  • Frequently asked questions
  • Sources and references

Authors

S
Shubham Jha

Share

TL;DR
  • ✓Mobile app penetration testing attacks the client binary, on-device storage, and the backend APIs an iOS or Android app talks to, graded against the OWASP MASVS standard and reproduced with the MASTG test cases.
  • ✓The attacker controls the device: they can root or jailbreak it, decompile the app with jadx or Hopper, dump shared_prefs with adb, and hook functions at runtime with Frida. Your binary is an untrusted, fully visible artifact.
  • ✓Static analysis (apktool, jadx, MobSF) finds the leads; dynamic analysis on a rooted or jailbroken device (Frida, objection, Burp) confirms which leads are real and exploitable.
  • ✓The findings that recur are cleartext tokens in shared_prefs (MASVS-STORAGE), hardcoded keys in the binary (MASVS-CRYPTO), and missing or one-script pinning (MASVS-NETWORK), not exotic zero-days.
  • ✓A single-platform engagement runs about 5 to 10 days and produces CVSS-scored findings, each tied to a MASVS control and a MASTG test ID.

Run MobSF over almost any production Android build and the score comes back in the 30s out of 100, with a wall of red rows before you have even opened a device. That gap is the point: a web pentest of your backend never touches the cleartext token in shared_prefs, the AES key compiled into a constants file, or the certificate pin a stock Frida script peels off in ten seconds. Those live on the client, and the client belongs to the attacker.

Mobile application penetration testing is the practice of attacking that client the way a real adversary does. This post walks the engagement end to end: where you start, the actual tool output you read along the way, how iOS and Android diverge, a sample findings table from a report, and the configuration changes that actually close the gaps.

Table of contents
  1. What is mobile app penetration testing?
  2. Where do you start when you unpack the binary?
  3. Static analysis only tells you what is possible
  4. How does dynamic analysis confirm a finding?
  5. How is iOS pentesting different from Android?
  6. A WebView that no one pinned
  7. What do the fixes actually look like?

What is mobile app penetration testing?

Mobile app penetration testing is an authorized security assessment of a mobile application's client code, its on-device data, and the backend APIs it calls, with the goal of finding and exploiting vulnerabilities before an attacker does. You report each one with reproduction steps, a CVSS score, and the OWASP MASVS control it violates.

It is fundamentally different from a server pentest because the threat model assumes the attacker owns the runtime. They root or jailbreak the device, decompile the app, read its private storage, hook its functions in memory, and tamper with its traffic. So the assessment treats the binary as a fully visible, fully controllable artifact, not a trusted black box. Risk categories come from the OWASP Mobile Top 10; the verifiable controls and test procedures come from MASVS and the MASTG.

How a mobile engagement runs
1
Scope
Pick the MASVS level, platforms, and whether resilience and the backend APIs are in scope.
2
Static
apktool + jadx + MobSF: map the surface and grep for hardcoded secrets and weak crypto.
3
Dynamic
Rooted/jailbroken device: Frida, objection, Burp confirm which leads are exploitable.
4
Backend
Test the APIs the app calls against intercepted traffic; most high-severity bugs live here.
5
Report
CVSS-scored findings, each tied to a MASVS control and a MASTG test ID.

Where do you start when you unpack the binary?

You start static, because it is free, fast, and tells you where to point the device phase. On Android the first move is to decode the package and look at what apktool reconstructs:

$ apktool d banking.apk -o src/
I: Using Apktool 2.9.3 on banking.apk
I: Baksmaling classes.dex...
I: Decoding AndroidManifest.xml with resources...

$ tree -L 2 src/
src/
├─ AndroidManifest.xml
├─ apktool.yml
├─ res/
├─ assets/
│  └─ config.properties   <- bundled config, always read this
└─ smali/

That config.properties in assets/ is the kind of file that ships secrets. The manifest tells you the attack surface (every exported="true" component is reachable). Then decompile to readable Java with jadx and grep the tree for the obvious mistakes:

$ jadx -d out/ banking.apk && grep -rniE 'secret|api[_-]?key|AES' out/sources/
out/sources/com/bank/crypto/KeyVault.java:14:
    private static final String AES_KEY = "j8Hk2Lp9QwRt5VxZ";  <- hardcoded 128-bit key
out/sources/com/bank/net/ApiClient.java:31:
    String API_SECRET = "sk_live_4eC39HqLyjWDarjt";

A symmetric key in KeyVault.java means every install ships the same key, so anything it encrypted on disk is decryptable by anyone with the APK. On iOS the equivalent entry is a decrypted IPA loaded into Hopper or Ghidra, with otool -L for linked libraries and class-dump for the Objective-C class layout.

Static analysis only tells you what is possible

Static findings are leads, not confirmed vulnerabilities. MobSF gives you a fast scored triage that ranks where to dig, but its score is a starting point, not a verdict:

$ docker run -p 8000:8000 opensecurity/mobile-security-framework-mobsf
# upload banking.apk, then read the summary:

Security Score : 38/100
Grade          : C
[HIGH]   App can be installed on a vulnerable Android version (minSdk 21)
[HIGH]   Debug certificate / android:debuggable could be true
[WARN]   App uses SharedPreferences in MODE_WORLD_READABLE pattern
[HIGH]   Hardcoded secrets found (3) - see 'Secrets' tab

MobSF flags that a string looks like a key and that a component is exported. What it cannot tell you is whether that token is live, whether the pin falls to a stock script, or whether the biometric gate protects a real authorization check or a cosmetic screen. Only the running app answers those questions, which is why the device phase exists.

How does dynamic analysis confirm a finding?

Dynamic analysis runs the app on a rooted or jailbroken device and proves which static leads are exploitable. The single most common confirmation is pulling the app's private storage after you have logged in and clicked around:

$ adb shell run-as com.bank.app cat shared_prefs/session.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
  <string name="auth_token">eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjQ0MTd9...</string>
  <string name="refresh">rt_9f2a7c1b04e3</string>
  <int name="pin" value="4417" />
</map>

That is a live JWT, a refresh token, and a user PIN in plaintext, readable on any rooted device. The next confirmation is the network layer. Proxy the app through Burp, and if it pins, attach Frida with objection's pinning bypass and watch it land:

$ objection -g com.bank.app explore
com.bank.app on (Pixel: 13) [usb] # android sslpinning disable
(agent) Custom TrustManager check bypassed
(agent) OkHttp 3.x CertificatePinner.check() bypassed
(agent) SSLContext.init() custom TrustManager injected
[+] Pinning bypassed. Traffic now visible in Burp.

Three lines of console output and the pin is gone. When the app refuses the proxy or uses raw sockets, you escalate to forced redirection, covered in intercepting proxy-unaware app traffic. This static-then-dynamic loop is exactly what agentic pentesting automates across many apps and methods at once.

Strobes insight
MobSF's score is a lead generator, not a verdict. A C-grade APK can be safe and an A-grade one exploitable. The device phase decides which static flags are real.

How is iOS pentesting different from Android?

The methodology and the MASVS controls are shared, but the platform internals diverge in ways that change your toolchain on day one. Android ships an APK you unpack with apktool and decompile with jadx; iOS ships an IPA with a Mach-O you must first decrypt (FairPlay), then disassemble in Hopper or Ghidra.

  • Secure storage: Android uses the Keystore and SharedPreferences; iOS uses the Keychain and plists/NSUserDefaults. Misuse on either side leaks tokens to a rooted or jailbroken attacker.
  • Privilege: Android needs root (Magisk) to run frida-server and read /data/data; iOS needs a jailbreak or a re-signed debug build.
  • IPC: Android exposes exported activities, services, and content providers (probe with Drozer); iOS uses URL schemes, universal links, and XPC.
  • Getting the binary: iOS code signing and FairPlay encryption mean you usually work from a decrypted IPA pulled off-device with frida-ios-dump.

The full per-control test list for both platforms lives in our mobile app penetration testing checklist.

A WebView that no one pinned

On a recent assessment of a retail banking app, the login and money-movement flows pinned their certificate flawlessly, and the team was rightly proud of it. The rewards section, though, loaded in a WebView with setJavaScriptEnabled(true) and an addJavascriptInterface bridge exposing a native object, with no pinning on that traffic at all. We MITM'd the rewards endpoint, injected JavaScript that called the exposed bridge, and reached native app context, including the same session token from the storage finding above. The happy path was bulletproof; the side door was wide open.

That is the recurring lesson. The exploitable findings are rarely zero-days in the binary. They are the storage the team forgot to encrypt, the SDK that pins separately from the host, and the one screen that skipped the control everything else enforced. Below is what that report excerpt looks like, scored and mapped to controls.

Sample findings excerpt from a mobile report
FindingSeverity (CVSS)EvidenceRemediation
Live session token + PIN in cleartext SharedPreferencesHigh (7.5)adb dump of session.xml: auth_token, refresh, pin=4417EncryptedSharedPreferences + Keystore; never store the PIN
Hardcoded AES-128 key in binaryHigh (7.4)jadx: KeyVault.AES_KEY = "j8Hk2Lp9..."Per-install key via KeyGenParameterSpec in Keystore
Certificate pinning bypassed by stock objectionMedium (5.9)objection sslpinning disable -> traffic visible in BurpServer-side short-lived tokens; pin-set + attestation
WebView addJavascriptInterface to native objectHigh (8.1)MITM rewards endpoint -> injected JS reached native contextRemove JS bridge for untrusted content; pin WebView traffic

What do the fixes actually look like?

Durable remediation is configuration, not advice to "use strong passwords." Each finding above has a concrete fix:

  • Cleartext token in shared_prefs: store it with EncryptedSharedPreferences backed by a Keystore master key (MasterKey.Builder(context).setKeyScheme(AES256_GCM).build()) on Android, or the Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly on iOS. Never store the PIN at all.
  • Hardcoded AES key: generate a per-install key in the Android Keystore (KeyGenParameterSpec with setUserAuthenticationRequired where appropriate) so the key never exists in the binary or leaves secure hardware.
  • Bypassable pin: pinning alone never stops a rooted attacker, but a Network Security Config (<pin-set> in network_security_config.xml) plus a real attestation check raises the cost; the durable control is server-side, with short-lived, scoped tokens that are useless once exfiltrated.
  • WebView bridge: remove addJavascriptInterface for untrusted content, set setJavaScriptEnabled(false) where possible, and pin the WebView's traffic too.

Treat client-side root and jailbreak detection as friction, not a boundary, because any client check can eventually be hooked. We map these controls to regulated data in mobile pentesting for data protection compliance.

Frequently asked questions

What is mobile application penetration testing?
It is an authorized security assessment of an iOS or Android app that attacks the client binary, on-device storage, and the backend APIs it calls. Testers decompile the app, dump its private storage, intercept its traffic, and instrument it at runtime, then report each issue with a CVSS score mapped to an OWASP MASVS control.
Do you need a jailbroken or rooted device?
For thorough dynamic analysis, yes. Root on Android (via Magisk) or a jailbreak on iOS lets you run frida-server, read protected app directories with run-as, and bypass pinning. Some checks run on non-rooted devices using re-signed debug builds or patched APKs, but storage and resilience testing are far easier with elevated access.
Is iOS or Android harder to test?
They take similar effort but stress different skills. Android is more open, so unpacking and instrumenting is quicker, but the exported-component IPC surface is large. iOS is more locked down, so just getting a decrypted IPA and a working frida-server on a current jailbreak is often the hard part, while its IPC surface is smaller.
How long does a mobile app pentest take and what does it cost?
A single-platform engagement typically runs 5 to 10 days depending on app size, feature count, and whether resilience controls are in scope, often landing in the low five figures. Testing both iOS and Android roughly doubles the client-side effort, though backend API findings carry over between platforms.
Is testing the backend API part of a mobile pentest?
Usually yes, and it should be. A mobile app is a thin client over an API, and many of the highest-severity findings (broken object-level authorization, mass assignment) live server-side. A mobile engagement should include the APIs the app calls, tested with Burp Suite against intercepted, pin-bypassed traffic.
What is the difference between OWASP MASVS and MASTG?
MASVS (Mobile Application Security Verification Standard) defines the requirements, the what, grouped into Storage, Crypto, Auth, Network, Platform, Code, and Resilience. MASTG (Mobile Application Security Testing Guide) is the how, with concrete test cases and tool walkthroughs, each carrying a stable ID like MASTG-TEST-0001 so a finding can cite the exact procedure used.

Sources and references

  • OWASP MASVS
  • OWASP MASTG
  • OWASP Mobile Top 10
S
Shubham Jha
Security Researcher, Strobes
Shubham Jha leads offensive security research at Strobes, focused on web and API exploitation and red team tradecraft.
Tags
Mobile SecurityPenetration TestingApplication Security

Stop chasing vulnerabilities Start reducing exposure

See how Strobes AI agents validate and fix your most critical exposures automatically.

Book a Demo
Continue Reading

Related Posts

Vulnerability validation: why most of your scanner backlog is noise - Strobes
Exposure ValidationApplication Security

Vulnerability Validation: Why Most of Your Scanner Backlog Is Noise

Vulnerability validation proves which scanner findings are real, reachable, and exploitable. Why manual triage fails and how agentic validation scales.

Jun 9, 202619 min
How to pentest single-page applications - React, Angular and Vue SPA security testing guide
Penetration TestingApplication Security

How to Pentest Single-Page Applications (React, Angular, Vue)

Learn how to pentest React, Angular, and Vue SPAs. Covers DOM XSS, client-side routing bypass, JS bundle secrets, and why traditional DAST scanners fail.

Jun 4, 202623 min
Bug bounty vs pentesting vs AI pentesting comparison featured image
Penetration TestingApplication Security

Bug Bounty vs. Pentesting vs. AI Pentesting: Which Model Fits Your AppSec Program?

Bug bounty vs pentesting vs AI pentesting: compare costs, coverage, compliance, and when to use each model. Build a layered AppSec testing strategy.

Jun 4, 202621 min