Mobile Application Security Testing: iOS and Android

Most security teams think about web apps. Their scanners, their checklists, their threat models — all web-first. Meanwhile, the mobile app ships to millions of devices, carries session tokens, stores sensitive data locally, and talks to the same backend APIs with almost no one watching.

This guide covers the OWASP Mobile Security Testing Guide (MSTG) methodology, the top vulnerability classes on iOS and Android, and how the mobile attack surface connects back to the web APIs you scan.

The OWASP MSTG and Mobile Top 10

The OWASP Mobile Application Security Verification Standard (MASVS) defines three security levels, and the MSTG is its companion test guide. The OWASP Mobile Top 10 maps the most critical vulnerability classes:

ID Vulnerability Short description
M1 Improper Credential Usage Hardcoded credentials, insecure auth flows, broken biometric auth
M2 Inadequate Supply Chain Security Malicious SDKs, compromised build pipelines, vulnerable third-party libraries
M3 Insecure Authentication/Authorization Missing server-side auth, client-side auth decisions, privilege escalation via API
M4 Insufficient Input/Output Validation SQL injection, XSS via WebViews, command injection in deep links
M5 Insecure Communication Missing certificate pinning, accepting invalid TLS certs, cleartext protocols
M6 Inadequate Privacy Controls Excessive data collection, insecure data sharing with third parties
M7 Insufficient Binary Protections No obfuscation, easy reverse engineering, missing root/jailbreak detection
M8 Security Misconfiguration Exposed debug endpoints, verbose error messages, insecure default settings
M9 Insecure Data Storage Plaintext secrets in SharedPreferences/NSUserDefaults/SQLite, world-readable files
M10 Insufficient Cryptography Broken algorithms (MD5, DES), hardcoded keys, ECB mode, weak key derivation

The Mobile Attack Surface

Mobile security testing splits across two primary surfaces: the client application running on the device, and the backend APIs it talks to. These require different testing techniques and tools, but findings in one area often lead to findings in the other.

Client-side surface

Network and API surface

Android Security Testing

Extracting and decompiling the APK

Start by getting the APK. From a connected device:

# List installed packages
adb shell pm list packages | grep -i targetapp

# Get the APK path
adb shell pm path com.example.targetapp

# Pull the APK
adb pull /data/app/com.example.targetapp-1/base.apk target.apk

Decompile with jadx for Java/Kotlin source reconstruction:

jadx -d output/ target.apk

Or use apktool to decompile smali and resources:

apktool d target.apk -o output/

Static analysis targets

After decompilation, search for common issues:

# Hardcoded secrets and API keys
grep -r "api_key\|api_secret\|password\|SECRET\|TOKEN" output/ --include="*.java"

# Insecure SharedPreferences (MODE_WORLD_READABLE)
grep -r "MODE_WORLD_READABLE\|MODE_WORLD_WRITEABLE" output/

# Cleartext network traffic allowed
grep -r "cleartext\|usesCleartextTraffic" output/

# Exported components (potential attack surface)
grep -r "android:exported=\"true\"" output/AndroidManifest.xml

# SQLite queries susceptible to injection
grep -r "rawQuery\|execSQL" output/ --include="*.java"

AndroidManifest.xml audit

The manifest defines the app's attack surface. Key things to check:

Dynamic analysis with Frida

Frida is the standard tool for runtime instrumentation — hooking into running app functions, bypassing certificate pinning, and extracting runtime secrets.

# Start Frida server on device (requires root or emulator)
adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"

# List running processes
frida-ps -U

# Attach to target and run a script
frida -U -l bypass-pinning.js com.example.targetapp

A common certificate pinning bypass script:

// OkHttp3 pinning bypass
Java.perform(function() {
    var CertificatePinner = Java.use('okhttp3.CertificatePinner');
    CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
        console.log('Certificate pinning bypassed: ' + arguments[0]);
    };
});

Data storage testing

# Pull app data directory (requires root)
adb shell "run-as com.example.targetapp ls /data/data/com.example.targetapp/"

# Check SharedPreferences (often cleartext XML)
adb shell "run-as com.example.targetapp cat /data/data/com.example.targetapp/shared_prefs/prefs.xml"

# Check SQLite databases
adb shell "run-as com.example.targetapp ls /data/data/com.example.targetapp/databases/"
adb pull /data/data/com.example.targetapp/databases/app.db
sqlite3 app.db .dump

iOS Security Testing

Environment setup

iOS testing requires either a jailbroken device or a device with a valid developer certificate running a re-signed app. Common tools:

Keychain analysis

The iOS Keychain stores credentials, tokens, and certificates. Accessibility attributes determine when items can be read:

Accessibility Risk
kSecAttrAccessibleAlways Accessible even when device is locked — high risk
kSecAttrAccessibleWhenUnlocked Standard — acceptable for most use cases
kSecAttrAccessibleAfterFirstUnlock Accessible after first unlock until reboot — background app use case
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly Best — requires device passcode, not backed up

With Objection on a jailbroken device:

# Start objection
objection -g com.example.targetapp explore

# Dump keychain
ios keychain dump

# List NSUserDefaults
ios nsuserdefaults get all

# Check plist files in app data directory
ios plist cat /var/mobile/Containers/Data/Application/.../Library/Preferences/com.example.targetapp.plist

iOS binary protections

# Check binary protections with otool
otool -hv TargetApp.app/TargetApp | grep -E "PIE|ASLR"

# Check for stack canaries
otool -Iv TargetApp.app/TargetApp | grep -E "stack_chk"

# Check for ARC (Automatic Reference Counting)
otool -Iv TargetApp.app/TargetApp | grep -c "_objc_release"

# Check encryption (0 = not encrypted = App Store DRM stripped)
otool -l TargetApp.app/TargetApp | grep -A4 LC_ENCRYPTION_INFO

iOS URL scheme and Universal Link testing

URL schemes and Universal Links define deep link entry points into the app. Test for:

# Trigger a deeplink from terminal (iOS Simulator)
xcrun simctl openurl booted "myapp://profile?id=12345&redirect=https://evil.com"

Network Traffic Interception

Both iOS and Android traffic can be intercepted with a proxy. Burp Suite is the standard tool. The general approach:

  1. Configure Burp proxy on your workstation (typically port 8080)
  2. Set the device's Wi-Fi proxy to point to your workstation
  3. Install the Burp CA certificate on the device as a trusted CA
  4. Browse the app — Burp captures all HTTP/HTTPS traffic

Certificate pinning will block this. Bypass approaches:

The Mobile API Attack Surface

The most impactful mobile vulnerabilities are usually in the backend APIs. Mobile apps expose API calls that the web app never makes — often because the mobile team added endpoints independently of the web team, without the same security review.

After capturing traffic with Burp, look for:

# Export Burp request log, grep for unique API paths
# In Burp: Target > Site Map > right-click > Copy URLs in this host

# Use ffuf to enumerate mobile API paths from wordlist
ffuf -u https://api.example.com/FUZZ -w /path/to/wordlist.txt \
  -H "Authorization: Bearer $TOKEN" \
  -mc 200,201,204,301,302,403

Common High-Impact Findings

Hardcoded credentials and API keys

The most common critical finding in mobile apps. Developers embed API keys directly in source code or resource files, assuming the app binary is opaque. It is not. Tools like MobSF (Mobile Security Framework) scan for these automatically.

Insecure data storage

Sensitive data written to locations accessible without root or sufficient protections:

Certificate pinning not implemented

Without pinning, an attacker on the same network can MitM the app with a forged certificate. This matters most for banking, fintech, and healthcare apps. Test by routing through Burp — if traffic is visible without Frida, pinning is not implemented.

Broken biometric authentication

Biometric auth that makes the cryptographic decision client-side rather than server-side. If the app checks "did the biometric succeed?" locally and then sends a request, bypass the check with Frida and watch the server honor it.

Tools Reference

Tool Platform Use case
MobSF iOS + Android Automated static + dynamic analysis, all-in-one mobile scanner
Frida iOS + Android Runtime instrumentation, pinning bypass, function hooking
Objection iOS + Android Frida-based exploration shell, storage dump, pinning bypass
jadx Android APK decompilation to Java source
apktool Android APK decompilation (smali) and repackaging
adb Android Device interaction, data pull, logcat
class-dump / dsdump iOS Extract Objective-C/Swift headers from binary
Burp Suite iOS + Android HTTP/HTTPS proxy for network traffic analysis
apk-mitm Android Patch APK to disable certificate pinning
Ghidra / Binary Ninja iOS + Android Native binary reverse engineering

Mobile Security Testing Checklist

Static analysis

Dynamic analysis

API testing

Ironimo's web application scanner covers the backend API surface of your mobile apps — the endpoints that handle authentication, authorization, and data access. Run Ironimo against your mobile backend to catch IDOR, broken auth, and injection vulnerabilities before your mobile app exposes them to millions of devices.

Start free scan
← Back to Blog