30 min read

> "Mobile applications are where the world's most sensitive data meets the world's most hostile environment — a device you carry in your pocket, connected to untrusted networks, running code you cannot verify." — Mobile security researcher

Learning Objectives

  • Understand mobile application architectures for Android and iOS
  • Perform static analysis and reverse engineering of mobile apps
  • Conduct dynamic analysis and runtime instrumentation with Frida and Objection
  • Intercept and analyze mobile application network traffic
  • Identify and exploit OWASP Mobile Top 10 vulnerabilities
  • Test mobile application backends and APIs

Chapter 30: Mobile Application Security

"Mobile applications are where the world's most sensitive data meets the world's most hostile environment — a device you carry in your pocket, connected to untrusted networks, running code you cannot verify." — Mobile security researcher

Mobile applications have become the primary interface through which billions of people interact with digital services. Banking, healthcare, communication, commerce, and entertainment all flow through apps installed on devices that users carry everywhere. For ethical hackers, mobile applications present a rich and complex attack surface that spans the client application itself, the communication channels it uses, the backend APIs it connects to, and the data it stores on the device.

Mobile security testing differs fundamentally from web application testing. While web applications run in a controlled browser environment, mobile apps have direct access to device hardware, sensors, local storage, and operating system APIs. They can store data in databases, shared preferences, keychains, and file systems. They communicate through multiple channels — HTTPS, WebSockets, custom protocols, push notifications, and inter-process communication. They interact with device features like cameras, GPS, biometrics, and Bluetooth. Each of these capabilities introduces potential vulnerabilities.

This chapter provides a comprehensive guide to mobile application security testing. We will examine the architectures of Android and iOS applications, learn to reverse engineer and statically analyze app packages, master dynamic analysis through runtime instrumentation with tools like Frida and Objection, intercept and analyze network traffic, walk through the OWASP Mobile Top 10 vulnerabilities, and test the backend APIs that mobile apps depend on. Throughout, we will apply these techniques to MedSecure's mobile application — a healthcare app used by medical providers to access patient records and manage IoT medical devices.

Caution — Legal and Ethical Boundaries

Mobile application security testing requires explicit authorization from the application owner. Testing apps from app stores without permission is unauthorized access, regardless of your intent. Additionally, reverse engineering may be restricted by terms of service or local laws (such as the DMCA in the United States). Always obtain written permission that specifically covers mobile application testing, reverse engineering, and API testing before beginning any assessment.

30.1 Mobile Application Architecture

Understanding mobile application architecture is the foundation of effective security testing. Android and iOS take fundamentally different approaches to application design, security, and user privacy.

30.1.1 Android Application Architecture

Android applications are distributed as APK (Android Package Kit) or AAB (Android App Bundle) files. An APK is essentially a ZIP archive containing:

AndroidManifest.xml — The application's declaration file, specifying package name, permissions, components (activities, services, broadcast receivers, content providers), intent filters, minimum SDK version, and hardware requirements.

classes.dex — Dalvik Executable files containing the compiled application code. Modern apps may have multiple DEX files (multidex). DEX bytecode can be decompiled back to Java or Kotlin source code with reasonable fidelity.

resources.arsc — Compiled resources including strings, layouts, and configuration values. String resources often contain API endpoints, configuration values, and sometimes hardcoded credentials.

res/ — Resource files including layouts, drawables, and XML configurations.

lib/ — Native libraries (.so files) for different CPU architectures (armeabi-v7a, arm64-v8a, x86, x86_64). These are compiled from C/C++ code using the NDK and are harder to reverse engineer than DEX bytecode.

assets/ — Raw asset files bundled with the application, which may include configuration files, databases, certificates, or other data.

META-INF/ — Signature information used to verify the APK's integrity and authenticity.

Android's security model relies on several key mechanisms:

Application Sandboxing. Each app runs in its own process with a unique Linux user ID. Apps cannot directly access each other's data unless explicitly shared through content providers or other IPC mechanisms.

Permission System. Apps must declare permissions in the manifest and request dangerous permissions at runtime (since Android 6.0). This includes access to camera, location, contacts, storage, and other sensitive capabilities.

SELinux. Security-Enhanced Linux provides mandatory access control, limiting what processes can do even if they achieve elevated privileges.

30.1.2 iOS Application Architecture

iOS applications are distributed as IPA (iOS App Store Package) files, which are ZIP archives containing:

The Application Binary — A Mach-O executable compiled from Swift or Objective-C source code. iOS binaries are compiled to native ARM code and are significantly harder to decompile than Android's DEX bytecode. App Store binaries are encrypted with FairPlay DRM.

Info.plist — The application's configuration file, similar to Android's manifest. Contains bundle identifier, version, required device capabilities, URL schemes, and permission usage descriptions.

Frameworks/ — Bundled frameworks and dynamic libraries.

Resources — Storyboards, asset catalogs, localization files, and other resources.

iOS security mechanisms include:

App Sandbox. Each app operates in its own sandbox directory with restricted access to the file system, other apps, and system resources.

Code Signing. All executable code must be signed by a valid Apple developer certificate. The kernel verifies signatures before executing code.

Keychain Services. iOS provides a secure credential storage system (Keychain) that encrypts sensitive data and controls access through access groups and protection classes.

App Transport Security (ATS). By default, iOS requires HTTPS for all network connections. Apps must explicitly declare exceptions for HTTP connections.

30.1.3 Hybrid and Cross-Platform Applications

Many modern apps use cross-platform frameworks:

React Native applications contain JavaScript bundles that run in a JavaScript engine. The JavaScript code can be extracted and analyzed as plaintext, often revealing business logic, API endpoints, and authentication flows.

Flutter applications compile Dart code to native ARM binaries, making reverse engineering more challenging than React Native but still feasible with specialized tools.

Cordova/Ionic applications are essentially web applications wrapped in a native container (WebView). The HTML, CSS, and JavaScript are stored in the app package and can be extracted directly.

Xamarin applications compile C# to native code (on iOS) or IL (on Android), with the latter being decompilable.

MedSecure Scenario — Application Architecture

MedSecure's provider app is built as a native Android application (Java/Kotlin) and a native iOS application (Swift). It connects to AWS backend services via REST APIs through API Gateway, uses AWS Cognito for authentication, stores patient data locally in an encrypted SQLite database for offline access, communicates with IoT medical devices via Bluetooth Low Energy (BLE), and uses push notifications for critical alerts. This architecture gives us multiple attack vectors: the APK/IPA itself, the API endpoints, the local data storage, the BLE communication, and the push notification system.

30.2 Static Analysis and Reverse Engineering

Static analysis examines the application without executing it. For mobile apps, this means decompiling the package, reviewing the source code, and identifying vulnerabilities in the application's design and implementation.

30.2.1 Android Static Analysis

APK Extraction and Decompilation. The first step is obtaining and decompiling the APK:

# Extract APK from a device (if installed)
adb shell pm list packages | grep medsecure
adb shell pm path com.medsecure.provider
adb pull /data/app/com.medsecure.provider-1/base.apk ./medsecure.apk

# Decompile with apktool (preserves resources and smali)
apktool d medsecure.apk -o medsecure_decompiled/

# Decompile with jadx (produces readable Java source)
jadx medsecure.apk -d medsecure_jadx/

# Or use jadx-gui for interactive analysis
jadx-gui medsecure.apk

Manifest Analysis. The AndroidManifest.xml reveals critical security information:

# Review the manifest for security issues
cat medsecure_decompiled/AndroidManifest.xml

Key things to check in the manifest: - Exported components: Activities, services, broadcast receivers, or content providers with android:exported="true" can be accessed by other apps. Unintentionally exported components are a common vulnerability. - Backup flag: android:allowBackup="true" enables ADB backup, which can extract app data including databases and shared preferences. - Debuggable flag: android:debuggable="true" in production is a critical finding — it allows attaching a debugger and accessing application data. - Permission requests: Excessive permissions indicate potential over-collection of user data. - Custom permissions: Custom permissions with protectionLevel="normal" can be requested by any app. - Intent filters: Deep links and custom URL schemes can be attack vectors.

Source Code Analysis. With decompiled source, search for common vulnerabilities:

# Search for hardcoded secrets
grep -rn "api_key\|apikey\|secret\|password\|token\|aws_" medsecure_jadx/
grep -rn "BEGIN RSA\|BEGIN PRIVATE\|BEGIN CERTIFICATE" medsecure_jadx/

# Search for insecure data storage
grep -rn "getSharedPreferences\|MODE_WORLD" medsecure_jadx/
grep -rn "SQLiteDatabase\|openOrCreateDatabase" medsecure_jadx/

# Search for insecure communication
grep -rn "http://\|setHostnameVerifier\|TrustAllCerts\|ALLOW_ALL" medsecure_jadx/

# Search for logging of sensitive data
grep -rn "Log\.\(d\|i\|v\|w\|e\)" medsecure_jadx/ | grep -i "password\|token\|ssn\|patient"

# Search for WebView vulnerabilities
grep -rn "setJavaScriptEnabled\|addJavascriptInterface\|setAllowFileAccess" medsecure_jadx/

# Search for SQL injection points
grep -rn "rawQuery\|execSQL" medsecure_jadx/

# Search for crypto issues
grep -rn "DES\|ECB\|MD5\|SHA1\|SecretKeySpec\|Cipher.getInstance" medsecure_jadx/

Native Library Analysis. If the app includes native libraries, analyze them for vulnerabilities:

# List native libraries
find medsecure_decompiled/lib/ -name "*.so"

# Analyze with strings
strings medsecure_decompiled/lib/arm64-v8a/libcrypto.so | grep -i "key\|secret\|password"

# Disassemble with Ghidra or IDA Pro for deeper analysis

30.2.2 iOS Static Analysis

iOS static analysis is more challenging due to code compilation and FairPlay encryption:

IPA Extraction. For authorized testing, obtain the IPA from the developer or decrypt it from a jailbroken device:

# On a jailbroken device, use frida-ios-dump or clutch to decrypt
# the binary (FairPlay DRM removal for analysis purposes)
frida-ios-dump -l  # List installed apps
frida-ios-dump com.medsecure.provider  # Dump decrypted IPA

# Extract the IPA (it's a ZIP file)
unzip MedSecure.ipa -d medsecure_ipa/

Binary Analysis. iOS binaries are Mach-O files:

# Get binary info
otool -h medsecure_ipa/Payload/MedSecure.app/MedSecure

# Check for PIE (Position Independent Executable)
otool -hv medsecure_ipa/Payload/MedSecure.app/MedSecure | grep PIE

# Check for stack canaries
otool -Iv medsecure_ipa/Payload/MedSecure.app/MedSecure | grep stack_chk

# Check for ARC (Automatic Reference Counting)
otool -Iv medsecure_ipa/Payload/MedSecure.app/MedSecure | grep objc_release

# Extract strings
strings medsecure_ipa/Payload/MedSecure.app/MedSecure | grep -i "api\|key\|secret\|http"

# Analyze with class-dump (Objective-C)
class-dump medsecure_ipa/Payload/MedSecure.app/MedSecure > medsecure_headers.h

# For deeper analysis, use Ghidra or Hopper Disassembler

Plist and Resource Analysis:

# Read Info.plist
plutil -p medsecure_ipa/Payload/MedSecure.app/Info.plist

# Check for ATS exceptions (insecure HTTP allowed)
plutil -p medsecure_ipa/Payload/MedSecure.app/Info.plist | grep -A 10 "NSAppTransportSecurity"

# Check URL schemes
plutil -p medsecure_ipa/Payload/MedSecure.app/Info.plist | grep -A 5 "CFBundleURLSchemes"

# Search for embedded databases, certificates, config files
find medsecure_ipa/Payload/MedSecure.app/ -name "*.db" -o -name "*.sqlite" \
  -o -name "*.plist" -o -name "*.json" -o -name "*.cer" -o -name "*.p12"

30.2.3 Automated Static Analysis Tools

Several tools automate mobile static analysis:

MobSF (Mobile Security Framework) — An all-in-one mobile security testing framework that performs automated static and dynamic analysis for both Android and iOS:

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

# Upload APK/IPA through the web interface at http://localhost:8000
# MobSF will automatically:
# - Decompile the app
# - Analyze the manifest/Info.plist
# - Search for hardcoded secrets
# - Check for insecure configurations
# - Review code for vulnerability patterns
# - Generate a comprehensive report

QARK (Quick Android Review Kit) focuses on Android-specific vulnerabilities.

Semgrep can be configured with mobile-specific rules for code pattern analysis.

Blue Team Perspective — Secure Development Practices

Defenders should integrate static analysis into the CI/CD pipeline using tools like MobSF, SonarQube with mobile plugins, or commercial solutions. Key practices include: never hardcoding secrets (use secure key stores), enabling ProGuard/R8 obfuscation for Android, enabling bitcode and stripping symbols for iOS, implementing certificate pinning, using the platform's secure storage (Keychain for iOS, Android Keystore), and disabling debugging and logging in production builds.

30.3 Dynamic Analysis and Instrumentation

Dynamic analysis examines the application while it runs, observing its behavior, intercepting function calls, and manipulating its execution at runtime.

30.3.1 Setting Up the Testing Environment

Android Testing Environment:

# Option 1: Physical device with USB debugging enabled
adb devices  # Verify device connection

# Option 2: Android Emulator (for non-ARM native apps)
emulator -avd Pixel_4_API_30

# Install the target application
adb install medsecure.apk

# Root access (for comprehensive testing)
# Use Magisk on physical devices or rooted emulator images

iOS Testing Environment:

For iOS, a jailbroken device is typically required for comprehensive dynamic analysis. Tools like checkra1n (for supported devices) or palera1n provide jailbreak capabilities. Alternatively, use corellium (cloud-based virtual iOS devices) for testing without physical hardware.

30.3.2 Frida — Runtime Instrumentation

Frida is the premier tool for mobile application dynamic analysis. It injects a JavaScript engine into the target process, allowing you to hook functions, modify behavior, and inspect data at runtime.

# Install Frida
pip3 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 the target application
frida -U com.medsecure.provider

Common Frida Scripts:

// Hook a specific method to view arguments and return values
Java.perform(function() {
    var LoginActivity = Java.use('com.medsecure.provider.LoginActivity');
    LoginActivity.authenticate.implementation = function(username, password) {
        console.log('[*] authenticate() called');
        console.log('    Username: ' + username);
        console.log('    Password: ' + password);
        var result = this.authenticate(username, password);
        console.log('    Result: ' + result);
        return result;
    };
});

// Bypass root detection
Java.perform(function() {
    var RootDetector = Java.use('com.medsecure.provider.security.RootDetector');
    RootDetector.isDeviceRooted.implementation = function() {
        console.log('[*] Root detection bypassed');
        return false;
    };
});

// Dump encryption keys
Java.perform(function() {
    var SecretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');
    SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function(key, alg) {
        console.log('[*] SecretKeySpec created');
        console.log('    Algorithm: ' + alg);
        console.log('    Key (hex): ' + bytesToHex(key));
        return this.$init(key, alg);
    };

    function bytesToHex(bytes) {
        var hex = [];
        for (var i = 0; i < bytes.length; i++) {
            hex.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2));
        }
        return hex.join('');
    }
});

30.3.3 Objection — Frida-Powered Mobile Exploration

Objection is built on top of Frida and provides a convenient command-line interface for common mobile testing tasks:

# Install Objection
pip3 install objection

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

# Install patched APK and connect
adb install medsecure_patched.apk
objection -g com.medsecure.provider explore

# Common Objection commands:
# Environment and app info
com.medsecure.provider on (agent) [usb] # env
com.medsecure.provider on (agent) [usb] # android hooking list classes
com.medsecure.provider on (agent) [usb] # android hooking list activities

# File system exploration
com.medsecure.provider on (agent) [usb] # ls /data/data/com.medsecure.provider/
com.medsecure.provider on (agent) [usb] # file download /data/data/com.medsecure.provider/databases/patients.db

# Keystore and credential access
com.medsecure.provider on (agent) [usb] # android keystore list
com.medsecure.provider on (agent) [usb] # android keystore dump

# SSL pinning bypass
com.medsecure.provider on (agent) [usb] # android sslpinning disable

# Root detection bypass
com.medsecure.provider on (agent) [usb] # android root disable

# SQLite database queries
com.medsecure.provider on (agent) [usb] # sqlite connect /data/data/com.medsecure.provider/databases/patients.db
com.medsecure.provider on (agent) [usb:patients.db] # .tables
com.medsecure.provider on (agent) [usb:patients.db] # SELECT * FROM patient_records LIMIT 5;

# Clipboard monitoring
com.medsecure.provider on (agent) [usb] # android clipboard monitor

# Shared preferences access
com.medsecure.provider on (agent) [usb] # android hooking get current_activity

30.3.4 iOS Dynamic Analysis

For iOS dynamic analysis, Frida and Objection work similarly:

# Connect to iOS device
frida-ps -U  # List processes

# Attach to app
frida -U MedSecure

# Objection for iOS
objection -g MedSecure explore

# iOS-specific commands
MedSecure on (agent) [usb] # ios keychain dump
MedSecure on (agent) [usb] # ios plist cat Info.plist
MedSecure on (agent) [usb] # ios cookies get
MedSecure on (agent) [usb] # ios nsurlcredentialstorage dump
MedSecure on (agent) [usb] # ios sslpinning disable
MedSecure on (agent) [usb] # ios jailbreak disable

30.4 Network Traffic Analysis

Mobile applications communicate with backend servers through various protocols. Intercepting and analyzing this traffic is essential for identifying authentication weaknesses, data exposure, and API vulnerabilities.

30.4.1 Setting Up Traffic Interception

Burp Suite Configuration for Mobile:

# 1. Configure Burp Suite proxy listener
# Proxy > Options > Add: Bind to all interfaces on port 8080

# 2. Configure device proxy
# Android: Settings > WiFi > Long press network > Modify > Proxy: Manual
#          Server: <your-ip>, Port: 8080
# iOS: Settings > WiFi > (i) > HTTP Proxy > Manual
#       Server: <your-ip>, Port: 8080

# 3. Install Burp's CA certificate on the device
# Export from Burp: Proxy > Options > Import/Export CA Certificate
# Android: Push cert and install via Settings > Security > Install from storage
# iOS: Browse to http://<proxy-ip>:8080 and install the profile

Android Certificate Installation (Android 7+):

Starting with Android 7 (Nougat), apps by default only trust system-level certificates, not user-installed ones. To intercept HTTPS traffic:

# Option 1: Modify the APK's network security config
# Add to AndroidManifest.xml:
# android:networkSecurityConfig="@xml/network_security_config"
# Create res/xml/network_security_config.xml:
# <network-security-config>
#   <debug-overrides>
#     <trust-anchors>
#       <certificates src="user" />
#     </trust-anchors>
#   </debug-overrides>
# </network-security-config>

# Option 2: Install as system certificate (requires root)
adb push burp-cert.pem /data/local/tmp/
adb shell
su
mount -o rw,remount /system
cp /data/local/tmp/burp-cert.pem /system/etc/security/cacerts/9a5ba575.0
chmod 644 /system/etc/security/cacerts/9a5ba575.0
mount -o ro,remount /system

30.4.2 Bypassing Certificate Pinning

Many security-conscious apps implement certificate pinning, which restricts which certificates the app trusts for specific domains. This prevents proxy-based interception.

// Frida script to bypass common SSL pinning implementations

// OkHttp3 CertificatePinner bypass
Java.perform(function() {
    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check.overload('java.lang.String', 'java.util.List')
            .implementation = function(hostname, peerCertificates) {
            console.log('[*] OkHttp3 pinning bypassed for: ' + hostname);
            // Do nothing - skip the check
        };
    } catch (e) {
        console.log('[-] OkHttp3 CertificatePinner not found');
    }

    // TrustManagerImpl bypass
    try {
        var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
        TrustManagerImpl.verifyChain.implementation = function() {
            console.log('[*] TrustManagerImpl bypass');
            return arguments[0];  // Return the untrusted chain as trusted
        };
    } catch (e) {
        console.log('[-] TrustManagerImpl not found');
    }

    // Generic X509TrustManager bypass
    try {
        var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
        var SSLContext = Java.use('javax.net.ssl.SSLContext');

        var TrustManager = Java.registerClass({
            name: 'com.test.TrustManager',
            implements: [X509TrustManager],
            methods: {
                checkClientTrusted: function(chain, authType) {},
                checkServerTrusted: function(chain, authType) {},
                getAcceptedIssuers: function() { return []; }
            }
        });

        console.log('[*] Custom TrustManager registered');
    } catch (e) {
        console.log('[-] X509TrustManager bypass failed: ' + e);
    }
});

Using Objection for simpler pinning bypass:

# Objection automatic SSL pinning bypass
objection -g com.medsecure.provider explore --startup-command "android sslpinning disable"

30.4.3 Analyzing Intercepted Traffic

With traffic flowing through your proxy, analyze:

Authentication Flows. Examine login requests, token generation, refresh mechanisms, and session management. Look for: - Credentials sent in plaintext - Weak token generation - Missing token expiration - Insecure token storage (cookies without secure/httponly flags)

API Requests. Document all API endpoints, parameters, and response formats. Test for: - Insecure Direct Object References (IDOR) — can you access other users' data by modifying IDs? - Missing or weak authorization on endpoints - Parameter tampering and business logic flaws - Excessive data exposure in API responses

Data Exposure. Check what data the app sends and receives: - Is sensitive data (SSN, medical records, passwords) encrypted in transit? - Does the API return more data than the app displays (over-fetching)? - Are error messages revealing implementation details?

Blue Team Perspective — Certificate Pinning Done Right

Implementing certificate pinning correctly requires: pinning to the leaf certificate or public key (not just the CA), implementing backup pins for certificate rotation, using HPKP or platform-specific pinning APIs, combining pinning with other integrity checks (root/jailbreak detection, debugger detection), and having a mechanism to update pins without an app update (dynamic pinning with secure initial distribution). Remember that pinning can be bypassed on rooted/jailbroken devices, so it is a defense-in-depth measure, not a standalone security control.

30.5 OWASP Mobile Top 10

The OWASP Mobile Top 10 provides a categorization of the most critical mobile application security risks. Understanding these categories structures our testing approach.

30.5.1 M1: Improper Platform Usage

Misuse of platform features or failure to use platform security controls. Examples include: - Not using the Keychain (iOS) or Android Keystore for sensitive data - Requesting excessive permissions - Improper use of biometric APIs - Misusing WebView components

Testing: Review manifest/Info.plist permissions, check data storage locations, verify biometric implementation, test WebView configurations.

30.5.2 M2: Insecure Data Storage

Sensitive data stored in insecure locations on the device:

# Android data storage locations to check
adb shell
run-as com.medsecure.provider  # or use root access

# Shared Preferences (often contain tokens, user settings)
cat /data/data/com.medsecure.provider/shared_prefs/*.xml

# SQLite databases
sqlite3 /data/data/com.medsecure.provider/databases/patients.db ".tables"
sqlite3 /data/data/com.medsecure.provider/databases/patients.db "SELECT * FROM sessions;"

# Internal storage files
ls -la /data/data/com.medsecure.provider/files/

# Cache
ls -la /data/data/com.medsecure.provider/cache/

# External storage (world-readable!)
ls -la /sdcard/Android/data/com.medsecure.provider/

# iOS data storage locations to check
# (on jailbroken device)
# App sandbox: /var/mobile/Containers/Data/Application/<UUID>/
# Documents/
# Library/Preferences/ (plist files)
# Library/Caches/
# Library/Application Support/
# tmp/

Testing checklist: - Are credentials stored in plaintext in SharedPreferences/NSUserDefaults? - Is the local database encrypted? What algorithm and key derivation? - Are sensitive files stored on external storage (world-readable on Android)? - Is data persisted in screenshots/snapshots when the app backgrounds? - Does the app properly clear sensitive data from memory?

30.5.3 M3: Insecure Communication

Communication vulnerabilities beyond the absence of HTTPS:

  • Using HTTP for any communication
  • Accepting invalid SSL/TLS certificates
  • Not implementing certificate pinning
  • Using weak cipher suites or outdated TLS versions
  • Transmitting sensitive data in URLs (logged by proxies and servers)
  • Missing hostname verification

30.5.4 M4: Insecure Authentication

Authentication weaknesses specific to mobile contexts:

  • Offline authentication with weak validation
  • Biometric authentication that falls back to weak alternatives
  • Missing session timeout
  • "Remember me" functionality that stores credentials insecurely
  • Client-side authentication decisions that can be bypassed

30.5.5 M5: Insufficient Cryptography

Crypto weaknesses in mobile applications:

// Example: Insecure crypto (hardcoded key, ECB mode, DES)
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
SecretKeySpec key = new SecretKeySpec("12345678".getBytes(), "DES");
cipher.init(Cipher.ENCRYPT_MODE, key);

// Secure alternative (AES-GCM, proper key derivation)
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);

Testing: Check for hardcoded encryption keys, weak algorithms (DES, RC4, MD5), insecure modes (ECB), improper IV/nonce handling, and custom crypto implementations.

30.5.6 M6: Insecure Authorization

Authorization flaws where the client makes access control decisions:

// Frida script to test client-side authorization
Java.perform(function() {
    // Hook the role check method
    var UserManager = Java.use('com.medsecure.provider.auth.UserManager');
    UserManager.getUserRole.implementation = function() {
        console.log('[*] Original role: ' + this.getUserRole());
        return 'ADMIN';  // Escalate to admin role
    };

    // Hook feature flag checks
    var FeatureManager = Java.use('com.medsecure.provider.FeatureManager');
    FeatureManager.isFeatureEnabled.implementation = function(feature) {
        console.log('[*] Feature check: ' + feature);
        return true;  // Enable all features
    };
});

30.5.7 M7: Client Code Quality

Code quality issues that create security vulnerabilities: buffer overflows in native code, format string vulnerabilities, type confusion errors, and unsafe use of system APIs.

30.5.8 M8: Code Tampering

The risk of an attacker modifying the app binary. Defense mechanisms include: - Integrity verification (checksum validation) - Root/jailbreak detection - Debugger detection - Emulator detection

Testing these defenses:

// Bypass root detection methods
Java.perform(function() {
    // Common root check: file existence
    var File = Java.use('java.io.File');
    File.exists.implementation = function() {
        var path = this.getAbsolutePath();
        var rootPaths = ['/system/app/Superuser.apk', '/system/xbin/su',
                        '/sbin/su', '/data/local/bin/su', '/data/local/xbin/su'];
        if (rootPaths.indexOf(path) >= 0) {
            console.log('[*] Root file check bypassed: ' + path);
            return false;
        }
        return this.exists();
    };

    // Common root check: Runtime.exec("su")
    var Runtime = Java.use('java.lang.Runtime');
    Runtime.exec.overload('java.lang.String').implementation = function(cmd) {
        if (cmd === 'su' || cmd === 'which su') {
            console.log('[*] Runtime.exec su check bypassed');
            throw Java.use('java.io.IOException').$new('Permission denied');
        }
        return this.exec(cmd);
    };
});

30.5.9 M9: Reverse Engineering

The ease with which an app can be reverse engineered to understand its logic, extract secrets, or develop exploits. Mitigations include code obfuscation, native code for sensitive logic, anti-debugging techniques, and environment detection.

30.5.10 M10: Extraneous Functionality

Debug features, test endpoints, or hidden functionality left in production builds:

# Search for debug/test indicators in decompiled code
grep -rn "DEBUG\|isDebug\|isTest\|staging\|localhost\|10\.0\.\|192\.168\." medsecure_jadx/
grep -rn "TODO\|FIXME\|HACK\|test_\|dev_" medsecure_jadx/
grep -rn "BuildConfig.DEBUG" medsecure_jadx/

30.6 Advanced Dynamic Analysis Techniques

Beyond basic Frida hooking and Objection commands, advanced dynamic analysis provides deeper insight into mobile application security.

30.6.1 Memory Analysis

Examining application memory at runtime can reveal sensitive data that is not properly protected:

// Frida script to scan memory for sensitive patterns
Java.perform(function() {
    // Search for credit card patterns in memory
    var pattern = "\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}";

    Process.enumerateRanges('r--', {
        onMatch: function(range) {
            try {
                var results = Memory.scanSync(range.base, range.size,
                    // Search for "password" string
                    "70 61 73 73 77 6f 72 64"  // "password" in hex
                );
                results.forEach(function(match) {
                    var context = Memory.readUtf8String(match.address, 100);
                    console.log('[Memory] Found at ' + match.address + ': ' +
                        context.replace(/[\x00-\x1f]/g, '.'));
                });
            } catch(e) {}
        },
        onComplete: function() {
            console.log('[*] Memory scan complete');
        }
    });
});

Key memory analysis concerns for mobile applications include credentials remaining in memory after logout, sensitive data not being zeroed after use, cryptographic keys persisting in memory beyond their needed lifetime, and patient health data accessible in memory dumps.

Android intents and deep links create inter-application communication channels that can be exploited:

# Test explicit intent to exported activities
adb shell am start -n com.medsecure.provider/.admin.AdminActivity

# Test implicit intents with data URIs
adb shell am start -a android.intent.action.VIEW \
  -d "medsecure://patient/12345" com.medsecure.provider

# Test broadcast injection
adb shell am broadcast -a com.medsecure.provider.SYNC_COMPLETE \
  --es status "success" --ei count 100

# Test content provider queries
adb shell content query --uri content://com.medsecure.provider.patients/records

# Fuzzing deep links with various payloads
adb shell am start -a android.intent.action.VIEW \
  -d "medsecure://patient/../../../etc/passwd"
adb shell am start -a android.intent.action.VIEW \
  -d "medsecure://redirect?url=https://attacker.com"
adb shell am start -a android.intent.action.VIEW \
  -d "medsecure://webview?url=javascript:alert(1)"

Deep link testing is particularly important because many modern apps use deep links for email-based authentication, password reset flows, and inter-app navigation. A vulnerable deep link handler can enable authentication bypass, phishing, and cross-site scripting within the application context.

30.6.3 Cryptographic Implementation Testing

Mobile applications frequently implement cryptography incorrectly. Runtime analysis can reveal these issues:

// Frida script to monitor all cryptographic operations
Java.perform(function() {
    // Monitor Cipher usage
    var Cipher = Java.use('javax.crypto.Cipher');
    Cipher.getInstance.overload('java.lang.String').implementation = function(transformation) {
        console.log('[Crypto] Cipher.getInstance("' + transformation + '")');

        // Flag weak algorithms
        var weakAlgos = ['DES', 'RC4', 'RC2', 'Blowfish', 'ECB'];
        weakAlgos.forEach(function(weak) {
            if (transformation.toUpperCase().indexOf(weak) !== -1) {
                console.log('[!] WEAK ALGORITHM: ' + transformation);
            }
        });

        return this.getInstance(transformation);
    };

    // Monitor key generation
    var KeyGenerator = Java.use('javax.crypto.KeyGenerator');
    KeyGenerator.init.overload('int').implementation = function(keySize) {
        console.log('[Crypto] KeyGenerator.init(' + keySize + ')');
        if (keySize < 128) {
            console.log('[!] WEAK KEY SIZE: ' + keySize);
        }
        return this.init(keySize);
    };

    // Monitor MessageDigest (hashing)
    var MessageDigest = Java.use('java.security.MessageDigest');
    MessageDigest.getInstance.overload('java.lang.String').implementation = function(algorithm) {
        console.log('[Crypto] MessageDigest.getInstance("' + algorithm + '")');
        if (algorithm === 'MD5' || algorithm === 'SHA-1' || algorithm === 'SHA1') {
            console.log('[!] WEAK HASH: ' + algorithm);
        }
        return this.getInstance(algorithm);
    };

    // Monitor SecureRandom usage
    var SecureRandom = Java.use('java.security.SecureRandom');
    SecureRandom.$init.overload().implementation = function() {
        console.log('[Crypto] SecureRandom created (default provider)');
        return this.$init();
    };

    console.log('[*] Cryptographic monitoring active');
});

Common findings from crypto monitoring include use of DES or 3DES instead of AES, ECB mode (which reveals patterns in encrypted data), hardcoded initialization vectors (IVs), MD5 or SHA-1 for password hashing instead of bcrypt/scrypt/Argon2, symmetric keys derived from predictable sources, and SecureRandom initialized with fixed seeds.

30.6.4 Biometric Authentication Testing

Many mobile apps use biometric authentication (fingerprint, face recognition). Testing should verify that biometric authentication is properly integrated with the application's security model:

// Frida script to test biometric authentication bypass
Java.perform(function() {
    // Hook BiometricPrompt callback
    try {
        var BiometricPrompt = Java.use('androidx.biometric.BiometricPrompt');
        var AuthenticationCallback = Java.use(
            'androidx.biometric.BiometricPrompt$AuthenticationCallback'
        );

        // Find instances of the callback
        Java.choose('androidx.biometric.BiometricPrompt$AuthenticationCallback', {
            onMatch: function(instance) {
                console.log('[*] Found BiometricPrompt callback: ' + instance);
            },
            onComplete: function() {}
        });
    } catch(e) {
        console.log('[-] BiometricPrompt not found: ' + e);
    }

    // Check if biometric result is validated server-side
    // or if it just unlocks a local gate
    // If purely client-side, it can be bypassed
});

The key question for biometric testing is whether the biometric result produces a cryptographic artifact (such as unlocking a key in the Android Keystore or iOS Keychain) that is required for subsequent operations, or whether it merely gates a client-side boolean check that can be trivially bypassed with Frida. The former is secure; the latter is a critical finding.

30.6.5 Screenshot and Task Switcher Protection

When a user switches away from a mobile app, the OS takes a screenshot for the task switcher animation. If the app displays sensitive data (patient records, credentials, financial information), this screenshot is stored on the device and may be accessible:

# Android: Check for task switcher screenshots
adb shell ls -la /data/system_ce/0/recent_images/
# Or
adb shell ls -la /data/system/recent_tasks/

# iOS: Check for snapshots
# Location: /var/mobile/Containers/Data/Application/<UUID>/Library/SplashBoard/Snapshots/

Testing procedure: 1. Navigate to a screen displaying sensitive data (patient records) 2. Press the home button or switch to another app 3. Check the task switcher — is the sensitive data visible in the thumbnail? 4. Check the filesystem for cached screenshots 5. Verify whether the app implements window flagging (FLAG_SECURE on Android, screenshot prevention on iOS)

30.7 Mobile Backend and API Testing

The backend APIs that mobile apps communicate with often contain more vulnerabilities than the apps themselves, because developers may assume the mobile app is the only client and skip server-side validation. When a mobile app calls an API, the developer controls the client — but an attacker can replace the client with any HTTP tool (curl, Burp Suite, custom scripts) and send arbitrary requests to the API. Every security control that exists only in the mobile app can be bypassed by communicating directly with the API.

This asymmetry makes API testing one of the most important aspects of mobile security assessment. During the OWASP Mobile Security Verification Standard (MASVS) assessment process, API security typically accounts for more critical findings than client-side issues.

30.7.1 Understanding Mobile API Architecture

Mobile applications typically communicate with backends through RESTful APIs, GraphQL endpoints, or WebSocket connections. Unlike web applications where the browser enforces same-origin policies, mobile apps can communicate with any server without cross-origin restrictions.

Authentication Patterns. Common mobile API authentication approaches include OAuth 2.0 with PKCE (the recommended approach for native mobile apps), JWT tokens with refresh flows, API keys combined with user authentication, and mutual TLS with client certificates for high-security applications. Testing should verify that the chosen pattern is correctly implemented end-to-end.

GraphQL Considerations. Mobile apps increasingly use GraphQL APIs, which have unique security testing requirements. GraphQL's introspection feature can expose the entire API schema if not disabled in production. Nested queries can enable denial-of-service through query depth attacks. Batch queries can bypass rate limiting. Authorization must be enforced at the resolver level because GraphQL's flexible queries mean traditional endpoint-based authorization does not apply.

30.7.2 API Discovery and Documentation

# Extract API endpoints from decompiled code
grep -rn "https\?://\|api/v[0-9]\|/api/\|\.com/\|\.io/" medsecure_jadx/ | \
  grep -v "google\|facebook\|crashlytics"

# Look for API documentation endpoints
# Common paths: /swagger, /api-docs, /swagger.json, /openapi.json
curl https://api.medsecure-example.com/swagger.json
curl https://api.medsecure-example.com/api-docs

# Extract from network traffic
# Use Burp Suite to capture all API calls during a complete app walkthrough

30.7.3 Authentication and Session Testing

# Test token behavior
# 1. Capture a valid authentication token
# 2. Test token expiration by replaying after waiting
# 3. Test token scope by accessing other users' resources
# 4. Test token invalidation after password change
# 5. Test token invalidation after logout

# Example: Test for IDOR
# Original request: GET /api/v1/patients/12345
# Modified: GET /api/v1/patients/12346
# If the second returns data, IDOR vulnerability exists

30.7.4 API-Specific Vulnerabilities

Mobile APIs frequently suffer from:

Broken Object Level Authorization (BOLA). The API does not verify that the authenticated user has access to the specific object they are requesting. This is the mobile equivalent of IDOR and is extremely common.

Mass Assignment. The API accepts and processes request parameters that the client should not be able to set (e.g., user role, account balance, subscription tier).

Excessive Data Exposure. The API returns full data objects, relying on the mobile app to filter what is displayed. An attacker examining the raw API response gets all the data.

Rate Limiting Absence. Mobile APIs often lack rate limiting on sensitive endpoints like login, OTP verification, and password reset, enabling brute-force attacks.

# Test for rate limiting on login
for i in $(seq 1 100); do
  curl -s -o /dev/null -w "%{http_code}" \
    -X POST https://api.medsecure-example.com/auth/login \
    -H "Content-Type: application/json" \
    -d '{"username":"test@test.com","password":"wrong'$i'"}'
  echo " - Attempt $i"
done

30.8 Third-Party Library and SDK Security

Modern mobile applications rely heavily on third-party libraries and SDKs. A typical mobile app includes 20-50 third-party dependencies for analytics, advertising, crash reporting, networking, social login, payment processing, and UI components. Each of these dependencies introduces its own attack surface and privacy implications.

30.8.1 Dependency Enumeration and Analysis

The first step in third-party library assessment is identifying all included libraries and their versions:

# Android: Extract library information from APK
# List native libraries
unzip -l app.apk | grep "lib/"

# Identify Java/Kotlin libraries from DEX classes
jadx -d output/ app.apk
find output/ -name "*.java" | sed 's|/[^/]*$||' | sort -u | head -50

# Check for known vulnerable libraries
# Use OWASP Dependency-Check or retire.js
dependency-check --scan ./output --format HTML --out ./report

# iOS: List frameworks
otool -L MedSecure.app/MedSecure
find MedSecure.app/Frameworks/ -name "*.framework" -maxdepth 1

# Automated library detection with MobSF
# MobSF identifies libraries and checks for known CVEs

30.8.2 Common Third-Party Library Vulnerabilities

Analytics and Tracking SDKs. Libraries like Firebase Analytics, Mixpanel, and Amplitude collect user behavior data. Misconfigured analytics SDKs may log sensitive information (patient names, medical record numbers, diagnostic codes) in analytics events that are transmitted to third-party servers. For HIPAA-regulated apps like MedSecure, any analytics SDK that processes PHI without a Business Associate Agreement (BAA) is a compliance violation.

// Frida script to monitor analytics event logging
Java.perform(function() {
    // Monitor Firebase Analytics events
    try {
        var FirebaseAnalytics = Java.use('com.google.firebase.analytics.FirebaseAnalytics');
        FirebaseAnalytics.logEvent.overload(
            'java.lang.String', 'android.os.Bundle'
        ).implementation = function(eventName, params) {
            console.log('[Analytics] Event: ' + eventName);
            if (params !== null) {
                var keys = params.keySet().toArray();
                for (var i = 0; i < keys.length; i++) {
                    console.log('  Param: ' + keys[i] + ' = ' + params.get(keys[i]));
                }
            }
            return this.logEvent(eventName, params);
        };
    } catch(e) {
        console.log('Firebase Analytics not found');
    }

    // Monitor Crashlytics custom keys (may contain sensitive data)
    try {
        var Crashlytics = Java.use('com.google.firebase.crashlytics.FirebaseCrashlytics');
        Crashlytics.setCustomKey.overload(
            'java.lang.String', 'java.lang.String'
        ).implementation = function(key, value) {
            console.log('[Crashlytics] Custom key: ' + key + ' = ' + value);
            return this.setCustomKey(key, value);
        };
    } catch(e) {
        console.log('Crashlytics not found');
    }
});

Advertising SDKs. Ad libraries (AdMob, Facebook Audience Network, Unity Ads) collect device identifiers, location data, and usage patterns. They may introduce JavaScript bridges for ad rendering that can be exploited for cross-site scripting within the app's WebView context. Some ad SDKs have historically included remote code execution capabilities for "dynamic ad serving" that could be abused.

Networking Libraries. OkHttp, Retrofit, and Alamofire handle HTTP communication. Outdated versions may have TLS vulnerabilities, certificate validation bypasses, or logging configurations that inadvertently expose request/response data. Check whether the app uses a custom TrustManager or SSLSocketFactory that weakens TLS verification.

Social Login SDKs. Facebook Login, Google Sign-In, and Apple Sign-In SDKs handle OAuth flows. Misconfigured OAuth redirect URIs, missing state parameters, and improper token validation can enable account takeover. Test whether the app validates the OAuth token audience (intended recipient) to prevent token reuse attacks.

30.8.3 Supply Chain Risk Assessment

Mobile app supply chain attacks are an increasing concern. Attackers may compromise a popular library's repository, inject malicious code into a commonly used SDK, or create typosquatted packages with names similar to legitimate libraries. During a mobile security assessment, verify:

  1. Library sources. Are dependencies pulled from official package repositories (Maven Central, CocoaPods, npm), or from unknown or self-hosted sources?
  2. Version pinning. Does the build system pin specific library versions, or does it use version ranges that could pull in a compromised update?
  3. Signature verification. Are downloaded libraries verified against known signatures or checksums?
  4. Minimization. Does the app include libraries that are not actually used? Unused libraries increase the attack surface without providing value.

Blue Team Perspective — Mobile SDK Governance

Defenders should implement an SDK governance program: maintain an approved list of third-party SDKs vetted for security and privacy compliance, require security review before adding new dependencies, monitor for CVEs in included libraries using tools like Snyk or Dependabot, ensure all analytics SDKs are configured to exclude sensitive data fields, and verify that BAAs are in place for any SDK that may process PHI. Automated CI/CD checks should verify that only approved SDKs are included in release builds.

30.9 Local Data Storage Deep Dive

Mobile applications store data locally for offline functionality, caching, and performance. This local storage is a rich target for attackers who gain physical access to a device or exploit a local file access vulnerability.

30.9.1 Android Data Storage Locations

Android apps can store data in multiple locations, each with different security characteristics:

# SharedPreferences (XML key-value pairs)
# Location: /data/data/<package>/shared_prefs/
adb shell run-as com.medsecure.app ls shared_prefs/
adb shell run-as com.medsecure.app cat shared_prefs/user_prefs.xml
# Common findings: auth tokens, user IDs, feature flags, session data

# SQLite Databases
# Location: /data/data/<package>/databases/
adb shell run-as com.medsecure.app ls databases/
adb pull /data/data/com.medsecure.app/databases/patients.db ./
sqlite3 patients.db ".tables"
sqlite3 patients.db "SELECT * FROM patient_records LIMIT 5;"
# Common findings: cached patient data, search history, message drafts

# Internal Storage Files
# Location: /data/data/<package>/files/
adb shell run-as com.medsecure.app ls -la files/
adb shell run-as com.medsecure.app cat files/config.json
# Common findings: config files, cached API responses, downloaded documents

# External Storage (world-readable on older Android versions)
# Location: /sdcard/Android/data/<package>/
adb shell ls -la /sdcard/Android/data/com.medsecure.app/
# Common findings: exported reports, images, backup files

# Cache Directory
# Location: /data/data/<package>/cache/
adb shell run-as com.medsecure.app ls cache/
# Common findings: HTTP cache with API responses, image cache, WebView cache

# Android Keystore
# Not directly readable, but test whether the app uses it for key storage
# Use Frida to monitor Keystore operations

30.9.2 iOS Data Storage Locations

# iOS data is stored in the app sandbox:
# /var/mobile/Containers/Data/Application/<UUID>/

# Find the app's UUID
find /var/mobile/Containers/Data/Application/ -name "com.medsecure*" 2>/dev/null
# Or use objection: env

# NSUserDefaults (plist file)
# Location: Library/Preferences/<bundle-id>.plist
plutil -p Library/Preferences/com.medsecure.app.plist
# Common findings: auth tokens, settings, cached user data

# SQLite Databases
find . -name "*.db" -o -name "*.sqlite" -o -name "*.sqlite3"
sqlite3 Library/Application\ Support/patients.sqlite3 ".tables"

# Keychain
# Use objection to dump Keychain entries for the app
# objection> ios keychain dump
# Check for overly permissive accessibility constants:
# kSecAttrAccessibleAlways - available even when device is locked (INSECURE)
# kSecAttrAccessibleWhenUnlocked - correct for most data

# Core Data (NSPersistentStore)
find . -name "*.sqlite" -path "*/CoreData/*"

# WebView Cache and Cookies
ls -la Library/Caches/
ls -la Library/WebKit/
ls -la Library/Cookies/

30.9.3 Encryption at Rest Assessment

Testing whether sensitive data is encrypted at rest requires examining both the storage mechanism and the encryption implementation:

Android EncryptedSharedPreferences. The Jetpack Security library provides EncryptedSharedPreferences that encrypts both keys and values using AES-256-SIV for keys and AES-256-GCM for values. Test whether the app uses this or standard SharedPreferences for sensitive data.

SQLCipher. Database encryption using SQLCipher is common for mobile apps handling sensitive data. Test whether the database can be opened without a passphrase (indicating no encryption) and whether the encryption key is derived from user input or hardcoded.

// Frida script to detect encrypted vs. unencrypted database usage
Java.perform(function() {
    // Monitor standard SQLite (unencrypted)
    var SQLiteOpenHelper = Java.use('android.database.sqlite.SQLiteOpenHelper');
    SQLiteOpenHelper.getWritableDatabase.overload().implementation = function() {
        console.log('[DB] Standard SQLiteOpenHelper.getWritableDatabase() called');
        console.log('[DB] Database name: ' + this.getDatabaseName());
        console.log('[!] WARNING: Using unencrypted SQLite database');
        return this.getWritableDatabase();
    };

    // Monitor SQLCipher (encrypted)
    try {
        var SQLCipherHelper = Java.use('net.sqlcipher.database.SQLiteOpenHelper');
        SQLCipherHelper.getWritableDatabase.overload(
            'java.lang.String'
        ).implementation = function(password) {
            console.log('[DB] SQLCipher getWritableDatabase() called');
            console.log('[DB] Database name: ' + this.getDatabaseName());
            console.log('[DB] Encryption password: ' + password);
            return this.getWritableDatabase(password);
        };
    } catch(e) {
        console.log('SQLCipher not present in this app');
    }
});

iOS Data Protection. iOS provides file-level encryption through Data Protection classes. The most secure class (NSFileProtectionComplete) makes files inaccessible when the device is locked. Test which protection class is applied to sensitive files using objection:

# Check Data Protection class for files
objection> ios plist cat Library/Preferences/com.medsecure.app.plist
# Then check the file attributes for protection class

MedSecure Scenario — Local Data Storage Findings

The MedSecure mobile assessment revealed critical local data storage issues. Patient vital signs were cached in an unencrypted SQLite database for offline access. Authentication tokens were stored in standard SharedPreferences (not EncryptedSharedPreferences) with no expiration. The app's HTTP cache directory contained full API responses including patient names, diagnoses, and medication lists. On iOS, the Keychain entries used kSecAttrAccessibleAlways, making credentials available even when the device was locked. A BFU (Before First Unlock) extraction of a seized device could recover all cached patient data without the device passcode.

30.10 Applying to MedSecure: Mobile Security Assessment

MedSecure's provider mobile app handles highly sensitive healthcare data. A comprehensive mobile security assessment would follow this structured approach:

  1. Static Analysis Phase: Decompile the APK/IPA, review the manifest for overly permissive configurations, search for hardcoded credentials and API keys, analyze cryptographic implementations, check for debug/test code.

  2. Dynamic Analysis Phase: Set up Frida/Objection instrumentation, bypass root/jailbreak detection, test local data storage for sensitive data exposure, examine encryption key management at runtime, test biometric authentication bypass.

  3. Network Analysis Phase: Configure proxy interception, bypass certificate pinning, map all API endpoints, test authentication and authorization, check for data exposure in API responses, verify encryption of PHI in transit.

  4. Backend API Phase: Test all discovered endpoints for BOLA/IDOR, test authorization boundaries (can a nurse access doctor-only data?), test rate limiting on authentication endpoints, check for mass assignment vulnerabilities, verify PHI handling compliance.

  5. BLE Communication Phase: Analyze BLE communication with IoT medical devices, test for unauthorized device pairing, check for data encryption in BLE communication, test for replay attacks on device commands.

Lab Exercise — Setting Up Mobile Testing

For your student home lab, set up a mobile security testing environment: install Android Studio with an emulator, install Frida and Objection, configure Burp Suite for mobile proxy interception, and practice with intentionally vulnerable apps like DIVA (Damn Insecure and Vulnerable App), InsecureBankv2, and the OWASP MSTG apps. These provide safe, legal targets for learning mobile testing techniques.

30.11 Mobile Security Testing Methodology

A structured mobile security testing methodology ensures comprehensive coverage and consistent results.

30.11.1 Pre-Engagement Planning

Before testing begins, establish:

Scope Definition. Define which platforms are in scope (Android, iOS, or both), which app versions will be tested, whether backend APIs are included, whether source code will be provided (white-box versus black-box), and whether physical device access is required.

Environment Setup. Prepare testing devices (rooted Android, jailbroken iOS), proxy tools (Burp Suite with mobile certificates), instrumentation tools (Frida, Objection, MobSF), and network isolation (prevent test traffic from reaching production).

Account Provisioning. Obtain test accounts at different privilege levels (standard user, admin, provider, patient) to test authorization boundaries. Never test with production accounts containing real data.

30.11.2 Testing Phases

Phase 1: Reconnaissance and Static Analysis (Day 1-2) - Obtain the APK/IPA for analysis - Decompile and review manifest/Info.plist - Run MobSF for automated static analysis - Manual code review for hardcoded secrets, crypto implementation, and authentication logic - Identify all API endpoints from source code - Map the application's data flow and trust boundaries

Phase 2: Dynamic Analysis (Day 2-3) - Install the application on test devices - Configure proxy interception - Bypass certificate pinning if present - Complete application walkthrough capturing all traffic - Test local data storage after usage (SharedPreferences, databases, cache) - Runtime instrumentation with Frida for security control bypass - Test biometric authentication, session management, and logout

Phase 3: API Testing (Day 3-4) - Document all discovered API endpoints - Test authentication mechanisms (token generation, expiration, invalidation) - Test authorization for every endpoint (BOLA/IDOR) - Test input validation and injection vulnerabilities - Test rate limiting on sensitive endpoints - Test error handling for information disclosure - Test mass assignment and excessive data exposure

Phase 4: Advanced Testing (Day 4-5) - Inter-process communication testing (intents, URL schemes) - Cryptographic implementation review - Memory analysis for sensitive data persistence - Background/screenshot protection - Push notification security - Third-party library vulnerability assessment - BLE/NFC/other communication channel testing (if applicable)

30.11.3 Reporting and Remediation

Mobile security reports should include OWASP Mobile Top 10 mapping for each finding, platform-specific remediation guidance (Android and iOS may require different fixes), API-specific findings separate from client-side findings, compliance implications (HIPAA for MedSecure, PCI DSS for payment apps), and a risk-prioritized remediation roadmap.

ShopStack Scenario — Mobile API Assessment

During the ShopStack mobile assessment, the team discovered that the shopping app's API returned full credit card numbers in the order history endpoint, even though the app only displayed the last four digits. The API also lacked rate limiting on the login endpoint — a test script successfully attempted 10,000 login requests in under a minute without being blocked. Additionally, the order tracking API was vulnerable to IDOR — modifying the order ID in the request returned other customers' order details, including names, addresses, and purchase history. These findings highlighted the common pattern of relying on the mobile app for security controls that should be enforced server-side.

30.12 Emerging Mobile Security Challenges

Super Apps. Applications like WeChat and Grab that provide multiple services within a single app create complex security boundaries. Mini-programs running within super apps share the host app's permissions, data access, and network capabilities. Testing must verify isolation between mini-apps and the host application, ensure that one mini-program cannot access another's data, and validate that the host app properly sandboxes JavaScript execution within mini-program WebViews. The attack surface is enormous — a vulnerability in any mini-program could potentially compromise the entire super app ecosystem.

Mobile Device Management (MDM) Bypass. Enterprise apps often rely on MDM policies for security — enforcing device encryption, minimum OS versions, passcode requirements, and app restrictions. Testing should verify whether security controls can be bypassed by removing MDM profiles, using unmanaged devices, or cloning the app to a non-managed device. A common finding is that MDM compliance checks are performed only at enrollment time, not continuously, allowing a device that later becomes non-compliant to continue accessing corporate data.

Privacy Regulations. GDPR, CCPA, and HIPAA impose strict requirements on mobile data collection, storage, and transmission. Mobile security assessments increasingly include privacy compliance verification. Key testing areas include: data minimization (does the app collect more data than necessary?), consent management (does the app obtain proper consent before collecting data?), data retention (does the app delete data when no longer needed?), and cross-border transfer (does the app transmit data to servers in jurisdictions that may not provide adequate protection?). For MedSecure, HIPAA compliance requires that all PHI stored locally is encrypted, all PHI transmitted over networks uses TLS 1.2+, and access to PHI is authenticated and logged.

5G Security Implications. The rollout of 5G networks introduces new attack surfaces including network slicing, edge computing, and increased device connectivity that affect mobile application security. 5G's lower latency enables real-time applications (telemedicine video, remote device control) that create new data flow patterns to test. Edge computing moves processing closer to users, potentially storing sensitive data at edge nodes with different security postures than centralized cloud infrastructure.

Flutter and Cross-Platform Framework Security. The increasing adoption of Flutter, React Native, and Kotlin Multiplatform creates new challenges. Flutter apps compile to native ARM code and are difficult to decompile — traditional tools like jadx are less effective. React Native apps bundle JavaScript that can be extracted and analyzed, but the native bridge layer requires separate testing. Security testers must adapt their tooling to each framework's compilation and runtime model.

On-Device AI and ML Models. Mobile apps increasingly run machine learning models locally using frameworks like Core ML (iOS) and TensorFlow Lite (Android). These models may contain sensitive training data that can be extracted, enable adversarial input attacks that manipulate model predictions, or expose proprietary algorithms through model extraction. Testing should include examination of bundled ML model files for embedded training data and assessment of model input validation. For healthcare applications like MedSecure, on-device ML models used for preliminary diagnostic screening raise additional concerns: a manipulated model could produce incorrect screening results, potentially delaying treatment or generating unnecessary alarm. The FDA increasingly scrutinizes AI/ML-based medical device software, adding regulatory complexity to the security assessment.

Passkeys and FIDO2. The industry transition from passwords to passkeys (based on FIDO2/WebAuthn) changes mobile authentication fundamentally. While passkeys are more resistant to phishing and credential theft than passwords, they introduce new testing considerations: Is the passkey properly bound to the device's secure enclave? Can the passkey registration flow be manipulated? Does the app properly handle fallback authentication when passkeys are unavailable? These new authentication patterns require updated testing methodologies.

30.13 Mobile Security Testing Lab Setup

Building an effective mobile security testing lab requires both hardware and software components:

30.13.1 Essential Hardware

  • Android test device: A Google Pixel device (Pixel 4a or newer) that can be easily unlocked and rooted with Magisk. Google's own devices receive timely updates and have well-documented root procedures.
  • iOS test device: An iPhone running a jailbreakable iOS version. The specific model depends on current jailbreak availability — check the jailbreak community for supported versions.
  • Wireless access point: A dedicated WiFi access point for isolating test traffic and performing man-in-the-middle attacks.
  • USB cables and adapters: USB-C cables, Lightning cables, and USB hubs for connecting multiple devices simultaneously.

30.13.2 Software Toolkit

# Android tools
# Install Android SDK Platform Tools (adb, fastboot)
# Install jadx for decompilation
# Install apktool for resource decoding
brew install jadx apktool  # macOS
# Or download from respective GitHub releases

# Frida and Objection
pip3 install frida-tools objection

# Download Frida server for your test device's architecture
# https://github.com/frida/frida/releases
# Push to 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 &

# MobSF (Mobile Security Framework)
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf

# Burp Suite configured for mobile proxy
# Install Burp CA certificate on test devices

30.13.3 Practice Targets

For legal, safe practice, use intentionally vulnerable applications:

  • DIVA (Damn Insecure and Vulnerable App): Android app with 13 challenges covering insecure logging, hardcoded secrets, insecure data storage, input validation, and access control.
  • InsecureBankv2: Android banking app with intentional vulnerabilities including weak authentication, developer backdoors, and insecure data storage.
  • OWASP MSTG apps: CrackMe challenges for both Android and iOS, ranging from basic to advanced difficulty.
  • DVHMA (Damn Vulnerable Hybrid Mobile App): Tests hybrid app vulnerabilities in WebView implementations.
  • iGoat (iOS): Intentionally vulnerable iOS app for learning iOS security testing.

Student Lab Tip

Start with DIVA on an Android emulator — it requires no physical device and covers fundamental concepts. Progress to InsecureBankv2 for a more realistic banking app assessment. Once comfortable with Android, move to iOS testing with a jailbroken device if available, or use the Corellium cloud-based iOS testing platform for remote access to jailbroken iOS devices. Document every finding as you practice — building a portfolio of mobile security reports is valuable for career development. Use the OWASP MASTG as your testing guide, working through each test case systematically to build comprehensive skills across all mobile security domains.

Summary

Mobile application security testing is a multifaceted discipline that requires understanding of platform-specific architectures, reverse engineering skills, runtime instrumentation capabilities, network analysis expertise, and API testing proficiency. Android and iOS present different challenges — Android apps are easier to decompile but harder to get deep system access without root, while iOS apps are harder to reverse engineer but offer rich analysis opportunities on jailbroken devices.

The tools we have explored — Frida for runtime instrumentation, Objection for streamlined mobile analysis, Burp Suite for traffic interception, MobSF for automated assessment, and jadx/apktool for static analysis — form a comprehensive toolkit for mobile security testing. The OWASP Mobile Top 10 provides a structured framework for categorizing the vulnerabilities we discover, while the OWASP MASTG (Mobile Application Security Testing Guide) offers detailed testing procedures for each category.

Our deep dive into third-party library security and local data storage assessment highlighted two areas that are frequently underestimated in mobile security testing. Third-party SDKs introduce supply chain risk and privacy concerns that extend beyond the app developer's direct control. Local data storage — SharedPreferences, SQLite databases, Keychain entries, and cache files — often contains sensitive data that survives app logout, device backup, and even device disposal if not properly encrypted and wiped.

The API testing dimension of mobile security cannot be overstated. As we demonstrated throughout this chapter, the mobile app is merely a client — an attacker can bypass every client-side security control by communicating directly with the API. BOLA, mass assignment, excessive data exposure, and missing rate limiting are among the most common and impactful findings in mobile security assessments. Every security validation must be enforced server-side, regardless of client-side implementation.

For MedSecure, mobile security is not just a technical concern — it is a patient safety concern. A compromised provider app could expose protected health information, enable unauthorized access to medical records, or even allow tampering with IoT medical device commands. The local data storage findings — unencrypted patient data in SQLite, authentication tokens in standard SharedPreferences, PHI in HTTP cache — each represent potential HIPAA violations with significant regulatory and financial consequences. The stakes elevate mobile security testing from a checklist exercise to a critical component of healthcare security assurance.

In the next chapter, we will explore an even more challenging domain: IoT and embedded systems hacking, where the physical and digital worlds converge and where security vulnerabilities can have direct physical consequences.


Next: Chapter 31 — IoT and Embedded Systems Hacking