Mobile security starts from one assumption — “the client can’t be trusted.” An app runs on the user’s device, so it can be analyzed, tampered with, and hooked at runtime. We assume any check done inside the client can be bypassed. This is our flow for testing Android/iOS apps, starting calmly from what lives where.
First, we sketch the trust boundaries
At the start we picture something like this — dividing up “how far can an attacker reach.”
[ user device — untrusted zone ]
app binary (decompilable / hookable) ← static/dynamic analysis
│
local storage (any plaintext tokens/keys?)
│
- - - - transport (is SSL pinning on? any plaintext?) - - - -
│ ← intercept via proxy
[ server — where real control must live ]
server APIs (BOLA/BFLA?) ← actually the core
The part we most want to stress is the bottom. Mobile testing isn’t done at the “app”; it’s meaningful only when it reaches the server APIs the app calls — the critical flaws often live in backend authorization.
Static analysis — open it up first
We decompile the APK/IPA to inspect code, resources, and config. Hardcoded API keys, secrets, hidden endpoints, and debug flags are more common than you’d think.
apktool d app.apk -o out/ # extract resources/config
jadx -d src/ app.apk # decompile to Java source
grep -rEi "api[_-]?key|secret|password|http://" out/ src/
Dynamic analysis — look while it runs (Frida)
We hook functions in the running app to watch and change how root/jailbreak detection or auth logic behaves at runtime — confirming first-hand why client checks can only be advisory.
// Frida: hook root detection to always return "safe"
Java.perform(function () {
var Sec = Java.use('com.app.security.RootCheck');
Sec.isDeviceRooted.implementation = function () {
return false;
};
});
Transport, storage, auth
Transport: to intercept via proxy we bypass SSL pinning, then check plaintext transport, sensitive exposure, parameter tampering.
Local storage: check for plaintext tokens/PII/keys in SharedPreferences/Keychain/DB.
Auth/session: token lifetime/refresh/binding, and whether biometrics are enforced only on the client.
Going deeper — the SDKs and libraries the app carries
Modern apps bundle many third-party SDKs (ads, analytics, payments, maps) and native libraries. A known flaw in one becomes a door. Targeted attackers (APT) often aim at these “parts you lean on,” so we fingerprint embedded components and check real exploitability with a 1-day mindset. (Related: How 0-days Are Found)
Field note: we’re often asked, “we obfuscated — isn’t that enough?” Obfuscation slows analysis but doesn’t stop it. We gently note that security must come from server-side controls, not the client.
FAQ
Both Android and iOS?
Storage, permissions, and bypasses differ per platform, so we recommend both — but server APIs are shared, so one test helps both sides.
Is testing just the app enough?
The app is only the entrance; the data gateway is the server API. So we look at app, transport, and server as one flow.
Closing
The client can’t be trusted — hold that one sentence and what to check in a mobile test falls into place. To look at your app and the server APIs behind it together, reach out at mobile penetration testing.