A mobile app ships its entire client to the attacker. Unlike a web front-end you can only observe, an APK sits on a device you fully control — decompile it, hook it, tamper with it, watch every request it makes. That inversion is the whole reason mobile testing is productive: the client is not a black box, it's evidence. This is the methodology I use to take an Android app from a downloaded APK to a report full of proven findings, framed around the OWASP Mobile Application Security Verification Standard (MASVS).
Setup and static teardown
Everything starts by pulling the app apart before it ever runs.
- Unpack the APK. Decompile to readable smali/Java and extract resources, the manifest, and native libraries. This reveals the app's structure, its permissions, and — very often — things the developer forgot were in there.
- Read the manifest carefully. Which components are
exported? An exported activity, service, broadcast receiver or content provider is reachable by any other app on the device, and each is an entry point.android:debuggable="true"and cleartext-traffic permissions are immediate flags. - Hunt for secrets in the bundle. Hardcoded API keys, credentials, signing material, third-party tokens, backend URLs and staging endpoints get shipped inside APKs constantly. Strings, resource files and native libs all hide them. A leaked key here is a finding on its own and often the pivot into backend testing.
- Note the security controls present (or absent): certificate pinning, root detection, obfuscation, tamper checks. These shape how the dynamic phase goes.
Dynamic analysis on a controlled device
Static tells you what could happen; dynamic proves what does. I run the app on a rooted device or emulator I control and instrument it.
- Intercept the traffic. Route the app through a proxy and read every request/response. The API behind the app is usually the real prize — the mobile client is often just the least-tested door into the same backend a web app talks to, and all the API security issues apply here too.
- Defeat certificate pinning when present. Pinning is a speed bump, not a wall; runtime instrumentation can bypass it so testing can continue. The point isn't "pinning is useless" — it's that pinning protects users on stock devices, not a tester with root, so it must never be the only control.
- Runtime hooking. Instrumenting method calls lets me watch what the app does with data, flip the results of root/tamper checks, and reach code paths the UI won't let me trigger normally.
The findings that recur
Across engagements the same high-value issues show up again and again:
Insecure data storage. The big one. Apps cache sensitive data — tokens, PII, full API responses, sometimes credentials — in shared preferences, SQLite databases, or files on external storage, frequently unencrypted. Anything on external storage or in a world-readable location is exposed to other apps and to anyone with device access. I always inventory exactly what the app writes to disk and in what form.
Weak or misused cryptography. Hardcoded keys (an encryption key baked into the APK protects nothing), deprecated algorithms, ECB mode, static IVs, and home-rolled crypto. The pattern is usually "crypto was used, but in a way that doesn't actually provide the guarantee they think."
Exported components and IPC. Exported activities that can be launched with crafted intents to bypass a login screen; content providers that leak data to other apps; broadcast receivers that act on unauthenticated intents. Each exported component is an interface an attacker's app can call directly.
Insufficient transport security. Cleartext traffic, accepting invalid certificates, or falling back to HTTP. Anything sensitive crossing the network unencrypted is interceptable on a hostile network.
Trusting the client. Business logic, price calculations, feature gating or "premium" checks enforced in the app rather than on the server. Because the attacker owns the client, any rule enforced only there is already broken — the same business-logic principle as on the web, sharpened by the fact that the client is fully attacker-controlled.
Mapping to MASVS
I structure the whole assessment against MASVS so findings map to a recognised standard rather than an ad-hoc list:
- STORAGE — what's persisted, and is it protected?
- CRYPTO — are keys and algorithms sound and correctly used?
- AUTH — session handling, token storage, biometric/local auth.
- NETWORK — TLS, pinning, cleartext.
- PLATFORM — exported components, IPC, WebView configuration.
- CODE / RESILIENCE — debuggable flags, tamper/root detection, obfuscation.
Each finding cites the MASVS control it violates, which makes the report actionable for developers and easy to re-test.
Fix guidance I give
- Store secrets server-side, never in the APK. If the client needs to authenticate to a backend, do it through a flow that doesn't require shipping a static secret.
- Encrypt sensitive local data with keys held in the platform keystore, and keep nothing sensitive on external storage.
- Enforce every security decision on the server. Root detection and pinning raise the cost for opportunistic attackers, but the backend must assume the client is compromised.
- Minimise exported components and authenticate every IPC entry point.
- Treat the mobile backend API as a first-class target and test it to the same standard as any web API.
The through-line: a mobile app hands the attacker the client, so the client cannot be trusted with anything that matters. Security has to live on the server; the app is just the most convenient window into it.
Shipping an Android or iOS app and want it assessed to MASVS with proven findings and fix guidance per issue? That's a service I offer — get in touch.