Mobile App Security Testing: Android and iOS Pentesting

Mobile apps handle sensitive data: banking credentials, health records, personal messages. Yet many apps ship with critical vulnerabilities. This guide covers how to find them.

Setting Up Your Lab

Android Testing Environment

# Option 1: Emulator
# Install Android Studio, create emulator WITHOUT Play Store
# (Play Store = Google integrity checks = harder to root)

# Option 2: Physical device (recommended)
# Buy a cheap Pixel, enable Developer Options
# OEM Unlock + flash rooted image

# Essential tools
pip install frida-tools objection
apt install jadx apktool adb

iOS Testing Environment

# Jailbroken device required for full testing
# iPhone 6s-X on iOS 14-15 with checkra1n
# Or use Corellium (cloud-based, expensive)

# Tools
brew install libimobiledevice ideviceinstaller
pip install frida-tools objection

Proxy Setup (Both Platforms)

# Install Burp Suite CA on device
# Android: Settings > Security > Install from storage
# iOS: Settings > Profile Downloaded > Install

# Bypass certificate pinning (covered below)

Android Security Testing

Step 1: Static Analysis

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

# Or download from APKPure/APKMirror

# Decompile with jadx
jadx -d output/ target.apk

# What to look for in decompiled code:
grep -r "password" output/
grep -r "api_key" output/
grep -r "secret" output/
grep -r "http://" output/  # Insecure connections
grep -r "MODE_WORLD_READABLE" output/  # Insecure file storage

Manifest Analysis

<!-- AndroidManifest.xml - Check for: -->

<!-- Exported components (accessible to other apps) -->
<activity android:name=".AdminActivity" android:exported="true"/>
<!-- Can be launched by malicious app! -->

<!-- Debuggable (should be false in production) -->
<application android:debuggable="true">
<!-- Allows attaching debugger, extracting data -->

<!-- Backup enabled (data can be extracted) -->
<application android:allowBackup="true">

<!-- Insecure permissions -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!-- Does a calculator app need contacts? -->

Step 2: Dynamic Analysis

# Install on device
adb install target.apk

# Monitor with Frida
frida -U -f com.target.app -l script.js

# Or use objection for easy analysis
objection -g com.target.app explore

# In objection:
android hooking list activities
android hooking list services
android intent launch_activity com.target.app.AdminActivity

# Check for insecure storage
android keystore list
android clipboard monitor

Certificate Pinning Bypass

Most apps pin certificates to prevent MITM. Bypass with Frida:

// frida-ssl-bypass.js
Java.perform(function() {
    // TrustManager bypass
    var TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    var SSLContext = Java.use('javax.net.ssl.SSLContext');
    
    var TrustManagerImpl = Java.registerClass({
        name: 'FakeTrustManager',
        implements: [TrustManager],
        methods: {
            checkClientTrusted: function(chain, authType) {},
            checkServerTrusted: function(chain, authType) {},
            getAcceptedIssuers: function() { return []; }
        }
    });
    
    var TrustManagers = [TrustManagerImpl.$new()];
    var sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, TrustManagers, null);
});
# Or use objection (easier)
objection -g com.target.app explore
android sslpinning disable

Common Android Vulnerabilities

## Storage
□ SharedPreferences with MODE_WORLD_READABLE
□ SQLite databases with sensitive data unencrypted
□ Credentials in plaintext files
□ Backup enabled with sensitive data

## Network
□ HTTP instead of HTTPS
□ Certificate pinning missing
□ SSL errors ignored in code

## Components
□ Exported activities without authentication
□ Broadcast receivers leaking data
□ Content providers with SQL injection

## Code
□ Hardcoded credentials/API keys
□ Debuggable in production
□ WebView with JavaScript enabled + file access

Example: Exported Activity Exploit

# Find exported activities
aapt dump xmltree target.apk AndroidManifest.xml | grep -A5 "activity"

# Launch directly (bypassing login)
adb shell am start -n com.target.app/.AdminActivity

# If it opens without authentication = vulnerability!

iOS Security Testing

Step 1: Extract and Decrypt IPA

# On jailbroken device, apps are encrypted
# Use frida-ios-dump to decrypt
pip install frida-ios-dump

# Connect to device
frida-ps -Ua  # List running apps

# Dump decrypted IPA
python dump.py "Target App"

Step 2: Static Analysis

# Unzip IPA
unzip target.ipa -d extracted/

# Find the binary
file extracted/Payload/Target.app/Target
# Mach-O 64-bit arm64 executable

# Extract strings
strings extracted/Payload/Target.app/Target | grep -i password
strings extracted/Payload/Target.app/Target | grep -i api

# Check Info.plist
plutil -p extracted/Payload/Target.app/Info.plist

# Look for:
# - URL schemes (can be hijacked)
# - ATS exceptions (insecure HTTP allowed)
# - Custom URL handlers

Step 3: Dynamic Analysis

# Use objection
objection -g "Target App" explore

# Dump keychain
ios keychain dump

# Check pasteboard
ios pasteboard monitor

# Hook methods
ios hooking watch class ViewController
ios hooking watch method "-[LoginVC validatePassword:]" --dump-args

# Disable jailbreak detection
ios jailbreak disable

Common iOS Vulnerabilities

## Storage
□ Sensitive data in UserDefaults (not encrypted)
□ Keychain items with wrong protection class
□ Data not cleared on logout
□ Cache containing sensitive info

## Network
□ ATS (App Transport Security) disabled
□ Certificate pinning missing
□ Sensitive data in URL parameters

## Binary
□ PIE disabled (no ASLR)
□ Stack canaries missing
□ ARC disabled (memory corruption possible)

## Code
□ Hardcoded credentials
□ Debugging symbols in release
□ Custom URL schemes without validation

Example: Keychain Extraction

# In objection
ios keychain dump

# Output:
# Account: [email protected]
# Service: com.target.app
# Data: SuperSecretPassword123
# Protection: kSecAttrAccessibleWhenUnlocked
#
# Problem: Password stored in plaintext in keychain
# Should use: Secure Enclave or encrypted data only

OWASP Mobile Top 10

#VulnerabilityWhat to Test
M1Improper Platform UsagePermissions, intents, keychain
M2Insecure Data StorageFiles, databases, logs, clipboard
M3Insecure CommunicationHTTPS, pinning, data in transit
M4Insecure AuthenticationSession handling, biometrics bypass
M5Insufficient CryptographyWeak algorithms, hardcoded keys
M6Insecure AuthorizationRole checks, privilege escalation
M7Client Code QualityBuffer overflows, format strings
M8Code TamperingIntegrity checks, repackaging
M9Reverse EngineeringObfuscation, anti-debugging
M10Extraneous FunctionalityDebug code, test backends

Testing Checklist

## Pre-Testing
□ Set up proxy with valid CA
□ Root/jailbreak device
□ Install Frida, objection
□ Bypass certificate pinning

## Static Analysis
□ Decompile/decrypt app
□ Search for hardcoded secrets
□ Analyze manifest/Info.plist
□ Check binary protections

## Storage Testing
□ Check local databases
□ Examine keychain/SharedPreferences
□ Review file permissions
□ Check logs and cache

## Network Testing
□ Capture all traffic
□ Test certificate pinning
□ Check for sensitive data in requests
□ Test API authentication

## Authentication
□ Test session handling
□ Attempt biometric bypass
□ Check for auth bypasses
□ Test account lockout

## Platform-Specific
□ Android: Test exported components
□ Android: Check backup settings
□ iOS: Test URL schemes
□ iOS: Check ATS settings

Reporting Template

## Finding: Sensitive Data in Application Logs

**Severity**: High

**Location**: LoggingUtil.java, line 47

**Description**: 
The application logs user passwords in plaintext when 
authentication fails, which can be accessed by any app 
with READ_LOGS permission.

**Steps to Reproduce**:
1. Install app on rooted device
2. Attempt login with wrong password
3. Run: adb logcat | grep password
4. Observe plaintext password in logs

**Impact**:
Malicious apps on the same device can harvest credentials.

**Recommendation**:
Never log sensitive data. Use logging frameworks that 
automatically redact sensitive fields.

**Code Fix**:
```java
// Before
Log.d("Auth", "Login failed for user: " + email + " password: " + password);

// After
Log.d("Auth", "Login failed for user: " + email);

## Conclusion

Mobile app security is vast, but the fundamentals are:

1. **Static analysis** — What does the code reveal?
2. **Dynamic analysis** — What does the app actually do?
3. **Data storage** — Is sensitive data protected?
4. **Network security** — Is communication secure?

Start with the easy wins (hardcoded secrets, insecure storage) before diving into complex reverse engineering.

---

*Related: [API Security: OAuth2 Vulnerabilities](/articles/api-security-oauth-vulnerabilities)*