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
Mobile App Penetration Testing Checklist (OWASP MASVS)
Application SecurityOWASP

Mobile App Penetration Testing Checklist (OWASP MASVS)

Likhil ChekuriMay 10, 20257 min read

Table of Contents

  • Storage is where most reports are won
  • How do you test network and certificate pinning?
  • What platform and code checks should you run?
  • Resilience checks matter only when the client enforces something
  • What do checklists routinely miss?
  • What do the fixes actually look like?
  • Frequently asked questions
  • Sources and references

Authors

L
Likhil Chekuri

Share

Table of Contents

  • Storage is where most reports are won
  • How do you test network and certificate pinning?
  • What platform and code checks should you run?
  • Resilience checks matter only when the client enforces something
  • What do checklists routinely miss?
  • What do the fixes actually look like?
  • Frequently asked questions
  • Sources and references

Authors

L
Likhil Chekuri

Share

TL;DR
  • ✓This checklist runs in yield order, not MASVS order: storage and network first (where the exploitable findings cluster), platform and code next, resilience last and only when scoped.
  • ✓Every test maps to a MASVS control group (Storage, Crypto, Auth, Network, Platform, Code, Resilience) and a verification level, so each finding cites a concrete control and MASTG test ID.
  • ✓Static tools (apktool, jadx, MobSF) generate leads; dynamic tools (Frida, objection, Burp, Drozer) on a rooted or jailbroken device confirm which leads are real.
  • ✓Treat any certificate pin that a stock objection one-liner defeats as effectively absent, and any root check the app logs but never branches on as decorative.
  • ✓Record each finding with its MASVS reference, a CVSS score, reproduction steps, and a configuration-level fix (EncryptedSharedPreferences, Keystore keys, network security config), not generic advice.

Two findings will earn most of your report on a typical mobile app: a secret sitting in cleartext on disk, and a certificate pin that a one-line script removes. The OWASP MASVS lists its control groups alphabetically, but you should not test them in that order. Test where the yield is.

This checklist runs storage and network first, platform and code second, and resilience last and only when it is in scope. It works for iOS and Android, with the divergences (Keychain vs Keystore, IPA vs APK) called out inline. Pair it with our overview of mobile app penetration testing for the methodology behind it.

Table of contents
  1. Storage is where most reports are won
  2. How do you test network and certificate pinning?
  3. What platform and code checks should you run?
  4. Resilience checks matter only when the client enforces something
  5. What do checklists routinely miss?
  6. What do the fixes actually look like?

Storage is where most reports are won

Test storage first because it produces the highest-severity findings for the least effort. The rule is blunt: nothing sensitive in cleartext, and no key bundled in the binary. After exercising every feature so the app has written its data, pull and read its private directory:

$ adb shell run-as com.target.app ls shared_prefs/
session.xml  analytics.xml  flags.xml

$ adb shell run-as com.target.app cat shared_prefs/session.xml
<map>
  <string name="auth_token">eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOjQ0MTd9...</string>
  <string name="pin">4417</string>   <- user PIN in cleartext
</map>

A live session token and a PIN in plain XML is a clean High. For crypto, decompile and grep for keys and weak modes; jadx makes hardcoded material trivial to spot:

$ jadx -d out/ app.apk && grep -rniE 'SECRET|KEY *=|"AES' out/sources/
out/sources/com/target/crypto/Cipher.java:22:
    Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");  <- ECB mode
out/sources/com/target/crypto/Cipher.java:9:
    static final byte[] KEY = "q1w2e3r4t5y6u7i8".getBytes(); <- hardcoded key

ECB plus a bundled key means identical plaintext blocks encrypt identically and every install shares one key. These map to MASVS-STORAGE and MASVS-CRYPTO (MASTG-TEST-0001 onward).

How do you test network and certificate pinning?

Route the app through Burp or mitmproxy with your CA installed, then answer two questions: does TLS validate correctly, and is the pin real? If traffic flows with your CA trusted, pinning is missing (MASVS-NETWORK gap). If it blocks, attempt the cheapest bypass and watch whether it lands:

$ objection -g com.target.app explore
com.target.app on (Pixel: 13) [usb] # android sslpinning disable
(agent) Found okhttp3.CertificatePinner, overriding check()
(agent) Found javax.net.ssl.TrustManagerImpl, overriding verifyChain()
(agent) SSLContext.init() pinned managers replaced
[+] SSL Pinning disabled. 4 hooks installed.

If those four hooks are all it takes, the pin offers little real protection and you write it up accordingly. When objection's stock hooks miss a custom implementation, fall back to a targeted Frida script on the exact pinning class. And when the app ignores the proxy entirely or uses raw sockets, switch to forced redirection, covered in intercepting proxy-unaware app traffic.

Strobes insight
Test in yield order, not alphabetical MASVS order. Storage and network produce most of the report; resilience often produces none and is frequently out of scope.

What platform and code checks should you run?

Platform checks examine how the app talks to the OS and other apps; code checks examine injection and debug hygiene. Dump the manifest, list every exported component, and launch them straight from adb to test for unauthorized actions:

$ grep -n 'android:exported="true"' src/AndroidManifest.xml
47:  <activity android:name=".AdminActivity" android:exported="true">
52:  <provider android:name=".DataProvider" android:exported="true">

$ adb shell am start -n com.target.app/.AdminActivity
Starting: Intent { cmp=com.target.app/.AdminActivity }
# admin screen opens with no auth - exported component, MASVS-PLATFORM
  • Probe exported providers and services with Drozer; test deeplinks and URL schemes for parameter injection and unauthorized actions.
  • Review WebViews for setJavaScriptEnabled, addJavascriptInterface exposure, and file:// access.
  • Check for debuggable builds, android:allowBackup="true", and secrets in logs (adb logcat | grep -i token).
  • Inventory third-party SDKs and their data flows, covered in our mobile SDK security testing methodology.

On iOS, test custom URL schemes and universal links for the same unauthorized-action issues. These map to MASVS-PLATFORM and MASVS-CODE.

Resilience checks matter only when the client enforces something

Resilience (MASVS-R) matters when the client itself enforces licensing, anti-fraud, or business rules the server cannot fully re-validate. It is not required for every app, so confirm scope before spending time here. Test root and jailbreak detection by running on a rooted device and trying the cheapest bypass first:

$ objection -g com.target.app explore
com.target.app on (Pixel: 13) [usb] # android root disable
(agent) Hooking RootBeer.isRooted() -> returning false
(agent) Hooking File.exists() for /system/bin/su -> false
[+] Root detection bypassed. App proceeded past the check.

If a single hook flips the result, the control is weak. On a recent assessment of a fintech app, the detection was worse than weak: the app called RootBeer.isRooted(), logged the boolean, and then never branched on it. The root check ran on every launch and changed nothing, so we did not even need the hook. The goal of resilience is not perfect protection (it does not exist) but enough friction to be meaningful; our guide on root detection and Android security shows real versus cargo-cult detection.

What do checklists routinely miss?

The biggest gap is testing only the happy path. You log in, tap through the main screens, and never invoke the exported admin activity, the password-reset deeplink, or the feature behind a flag, which is exactly where broken authorization hides. Walk every exported component and every URL scheme, not just the UI you reach by tapping.

The second gap is trusting static tools. MobSF tells you a string looks like a key and a component is exported; it cannot tell you the token is live, the pin is bypassable, or the biometric gate protects a real check. Confirm every static flag dynamically with Frida before you write it. The findings table below shows what a confirmed-and-scored excerpt looks like, with the config-level fix for each.

Mobile pentest checklist by MASVS category
Storage (test first)
  • ✓No cleartext tokens/PII in SharedPreferences, plists, SQLite, or external storage
  • ✓Keychain/Keystore used for secrets, not the binary
  • ✓Sensitive data cleared on logout; no leaks in backups or logs
Crypto
  • ✓No hardcoded keys, ECB mode, or static IVs
  • ✓Strong algorithms only (no MD5/SHA1 for security)
  • ✓Keys generated and stored in Keystore/Keychain
Network (test second)
  • ✓TLS validated; attacker CA rejected
  • ✓Pinning not defeated by stock objection/Frida
  • ✓Cleartext (HTTP) traffic blocked
Auth
  • ✓Tokens scoped, expiring, invalidated on logout
  • ✓Biometric/local auth not bypassable via Frida hook
  • ✓No credentials cached in memory longer than needed
Platform
  • ✓Exported components reviewed and probed with Drozer
  • ✓Deeplinks/URL schemes validate input and authorization
  • ✓WebView JS bridges and file access locked down
Code
  • ✓Not debuggable; allowBackup disabled
  • ✓No secrets logged
  • ✓Third-party SDKs inventoried and data flows reviewed
Resilience (only if scoped)
  • ✓Root/jailbreak detection resists Frida/objection bypass
  • ✓Detection result is actually branched on, not just logged
  • ✓App integrity/signature checks in place

What do the fixes actually look like?

Every finding gets a concrete configuration change, not generic advice. For the storage finding, replace plain SharedPreferences with the encrypted variant backed by a Keystore master key:

// Android - EncryptedSharedPreferences, key never leaves the Keystore
val key = MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build()
val prefs = EncryptedSharedPreferences.create(
    context, "session", key,
    PrefKeyEncryptionScheme.AES256_SIV,
    PrefValueEncryptionScheme.AES256_GCM)
  • Hardcoded key + ECB: generate a per-install key via KeyGenParameterSpec in the Keystore and use AES/GCM/NoPadding; on iOS, the Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly.
  • Missing or weak pin: declare a <pin-set> in network_security_config.xml and set cleartextTrafficPermitted="false", but rely on short-lived, scoped server-side tokens as the real control.
  • Exported AdminActivity: set android:exported="false" or require a signature-level permission, and enforce server-side authorization regardless.

Treat client-side root detection as friction, not a boundary, and tie each fix back to the control it satisfies so the right team owns it.

Confirmed findings excerpt with config fixes
FindingSeverity (CVSS)EvidenceRemediation
Auth token + PIN in cleartext shared_prefsHigh (7.5)adb run-as cat session.xmlEncryptedSharedPreferences + Keystore master key
Hardcoded AES key in ECB modeHigh (7.4)jadx: Cipher.java KEY=, AES/ECBPer-install Keystore key, AES/GCM/NoPadding
Exported AdminActivity reachable, no authHigh (8.1)adb am start -n .AdminActivity opens adminexported=false + server-side authorization
Pinning removed by stock objectionMedium (5.9)android sslpinning disable, 4 hookspin-set + short-lived scoped server tokens
Root check logged but never enforcedLow (3.1)RootBeer result logged, no branchBranch on result; add attestation as friction

Frequently asked questions

What is the difference between MASVS-L1, L2, and R?
L1 is the baseline every app should meet. L2 adds defense-in-depth for apps handling sensitive data such as banking or health. R adds resilience against reverse engineering and tampering (anti-debug, anti-instrumentation, integrity checks) for apps where the client enforces protections like DRM or anti-fraud. Scope an engagement to the level matching the app's risk.
Which mobile pentest checks find the most issues?
Insecure local storage is the top source of exploitable findings, followed by missing or weak certificate pinning, and exported components or unvalidated deeplinks. That is why this checklist runs storage and network first. Resilience checks, by contrast, often produce nothing and are frequently out of scope.
Do I need a rooted or jailbroken device for the checklist?
For the dynamic checks (storage dumps with run-as, pinning bypass, runtime hooking, resilience testing), yes. Root via Magisk on Android or a jailbreak on iOS lets you run frida-server and read protected directories. The static checks with MobSF, jadx, and apktool run without a device.
How do you test SSL certificate pinning?
Proxy the app through Burp or mitmproxy with your CA installed. If the app blocks, attempt objection's android sslpinning disable, which hooks OkHttp CertificatePinner, TrustManagerImpl, and SSLContext. If those stock hooks defeat it, the pinning is weak; if traffic flows immediately with your CA, pinning is missing entirely. A custom implementation may need a targeted Frida script.
Is resilience testing always required?
No. MASVS-R applies to apps where the client enforces business rules an attacker would want to bypass, like licensing, gaming anti-cheat, or fraud controls. A content app handling no sensitive data usually needs only L1, sometimes L2. Confirm the target level during scoping so you neither over-test nor under-test.
What does a real finding entry look like?
It pairs evidence with a fix: for example, 'auth token in cleartext shared_prefs (CVSS 7.5, evidence: adb run-as cat session.xml), remediated with EncryptedSharedPreferences backed by a Keystore master key.' Every entry cites its MASVS control and MASTG test ID so the developer can reproduce and verify the fix.

Sources and references

  • OWASP MASVS
  • OWASP MASTG
  • OWASP MASVS Levels
L
Likhil Chekuri
Application Security Engineer, Strobes
Likhil Chekuri is an AppSec engineer at Strobes who has run hundreds of web, mobile, and cloud penetration tests for regulated industries.
Tags
Mobile SecurityOWASPPenetration Testing

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