Android Application Pentesting
A comprehensive skill for security testing Android applications, from initial reconnaissance to exploitation of common vulnerabilities.
Quick Start
# Basic APK analysis
adb shell pm list packages -f | grep <package-name>
# Extract and analyze APK
adb pull /data/app/<package-name>/base.apk
apktool d base.apk -o <output-dir>
# List exported components
adb shell dumpsys package <package-name> | grep -A 5 "exported"
Android Security Model
Core Concepts
UID Separation: Each app runs under a unique User ID. Apps can only access their own files or shared files. Only the app itself, OS components, and root can access app data.
Sandboxing: Android 5.0+ enforces SELinux, denying all process interactions by default and only allowing expected ones through policies.
Permissions: Declared in AndroidManifest.xml via <uses-permission> elements. Types:
- Normal: Auto-granted, no user approval needed
- Dangerous: Requires user approval, grants elevated access
- Signature: Only apps signed with same certificate
- SignatureOrSystem: Same certificate OR system-level access
Permission Analysis
# List app permissions
adb shell dumpsys package <package-name> | grep -A 100 "requested permissions"
# Check granted permissions
adb shell dumpsys package <package-name> | grep -A 100 "granted permissions"
APK Structure Analysis
Extract and Decompile
# Pull APK from device
adb pull /data/app/<package-name>/base.apk ./
# Decompile with apktool
apktool d base.apk -o decompiled/
# Extract resources
unzip -l base.apk | grep -E "(AndroidManifest|classes.dex|META-INF)"
Key Files to Analyze
| File | Purpose | Security Relevance |
|---|---|---|
AndroidManifest.xml |
App configuration | Exported components, permissions, intent filters |
classes.dex |
Compiled code | Business logic, vulnerability patterns |
META-INF/CERT.RSA |
Certificate | App signing verification |
lib/ |
Native libraries | Native code vulnerabilities |
assets/ |
Additional files | Hidden code, malware |
Smali Analysis
# Decompile DEX to Smali
dex2jar base.apk
jad-decompile classes-dex2jar.jar
# Or use apktool (includes smali)
apktool d base.apk -o decompiled/
# Smali code in decompiled/smali/
Component Enumeration
Activities
# List all activities
adb shell dumpsys package <package-name> | grep -A 100 "activities"
# Find exported activities
adb shell dumpsys package <package-name> | grep "exported=" | grep "true"
# Check intent filters
adb shell dumpsys package <package-name> | grep -A 5 "intent-filter"
Services
# List services
adb shell dumpsys package <package-name> | grep -A 100 "services"
# Find exported services
adb shell dumpsys package <package-name> | grep "service.*exported"
# List running services
adb shell service list
Broadcast Receivers
# List receivers
adb shell dumpsys package <package-name> | grep -A 100 "receivers"
# Find exported receivers
adb shell dumpsys package <package-name> | grep "receiver.*exported"
Content Providers
# List providers
adb shell dumpsys package <package-name> | grep -A 100 "providers"
# Check provider permissions
adb shell dumpsys package <package-name> | grep -A 5 "provider"
Intent Vulnerability Testing
Implicit Intent Testing
# Test VIEW intent with custom scheme
adb shell am start -a android.intent.action.VIEW \
-d "<scheme>://<host>/<path>"
# Test SEND intent
adb shell am start -a android.intent.action.SEND \
-t "text/plain" \
-e android.intent.extra.TEXT "test payload"
Deep Link Exploitation
# Generic implicit VIEW (custom scheme)
adb shell am start -a android.intent.action.VIEW \
-d "<scheme>://<host>/<path>?param=value"
# Explicitly target specific Activity
adb shell am start -n <package>/<Activity> \
-a android.intent.action.VIEW \
-d "<scheme>://<host>/<path>"
# Test javascript: payload (if scheme validation is weak)
adb shell am start -a android.intent.action.VIEW \
-d "<scheme>://<host>/web?url=javascript:alert(1)"
Deep Link Discovery
# Find exported activities with VIEW + BROWSABLE
grep -r "android.intent.action.VIEW" decompiled/AndroidManifest.xml
grep -r "android.intent.category.BROWSABLE" decompiled/AndroidManifest.xml
# Extract custom schemes
grep -oP 'android:scheme="\K[^"]+' decompiled/AndroidManifest.xml
Common Deep Link Attack Vectors
- Open Redirect:
myapp://host/path?redirect=https://attacker.tld - Auth Bypass:
myapp://host/login?token=<malicious-token> - WebView Injection:
myapp://host/web?url=javascript:alert(1) - Parameter Pollution:
myapp://host/action?param=value¶m=malicious
AIDL/Binder Service Testing
Service Discovery
# List all running services
adb shell service list
adb shell am list services
# Output format:
# 145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
# 146 wifi : [android.net.wifi.IWifiManager]
Service PING (Interface Check)
# Transaction code 0x5f4e5446 (1598968902) returns interface name
adb shell service call <service-name> 1
# Valid response returns interface name as UTF-16 string
Transaction Calling
# Syntax: service call <name> <code> [type value ...]
# Types: i32 <int>, i64 <long>, s16 <string>
# Example: call transaction 8 with int parameter 1
adb shell service call mtkconnmetrics 8 i32 1
Brute-Force Method Discovery
# Iterate transaction codes to find valid methods
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
adb shell service call <service-name> $i 2>/dev/null | head -1
done
Method Mapping via onTransact()
# Decompile service implementation
dex2jar <service-jar>
# Search for onTransact switch statement
grep -A 100 "onTransact" <decompiled-class>
# Look for:
case TRANSACTION_methodName: // code
data.enforceInterface(DESCRIPTOR);
int param = data.readInt();
methodName(param);
reply.writeNoException();
return true;
Permission Check Analysis
# Look for missing permission checks in service implementation
grep -B 5 -A 10 "updateCtaAppStatus\|startMonitor\|privileged" <smali-file>
# Vulnerable pattern (no permission check):
private void updateCtaAppStatus(int uid, boolean status) {
// No permission check - VULNERABLE
/* privileged code */
}
# Secure pattern:
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
Content Provider Testing
Provider Enumeration
# List all providers for app
adb shell dumpsys package <package-name> | grep -A 20 "provider"
# Check read/write permissions
grep -A 5 "<provider" decompiled/AndroidManifest.xml
Provider Access Testing
# Query provider
adb shell content query --uri "content://<authority>/<path>"
# Insert test data
adb shell content insert --uri "content://<authority>/<path>" \
--bind "column1:string:value1"
# Update data
adb shell content update --uri "content://<authority>/<path>" \
--bind "column1:string:newvalue" \
--selection "column2=?" --selection-arg "value2"
# Delete data
adb shell content delete --uri "content://<authority>/<path>" \
--selection "column=?" --selection-arg "value"
SQL Injection Testing
# Test in selection parameter
adb shell content query --uri "content://<authority>/<path>" \
--selection "1=1 OR 1=1"
# Test in projection
grep -r "projection" decompiled/smali/ | grep -v "projectionMap"
WebView Security Testing
WebView Configuration Analysis
# Find WebView usage
grep -r "WebView" decompiled/smali/
# Check JavaScript enabled
grep -r "setJavaScriptEnabled" decompiled/smali/
# Check file access
grep -r "setAllowFileAccess" decompiled/smali/
# Check content access
grep -r "setAllowContentAccess" decompiled/smali/
JavaScript Bridge Testing
# Find @JavascriptInterface methods
grep -r "@JavascriptInterface" decompiled/smali/
# Test bridge injection
adb shell am start -a android.intent.action.VIEW \
-d "<scheme>://<host>/web?callback=javascript:alert(1)"
Pre-Installed App Analysis
System App Discovery
# List system apps
adb shell pm list packages -s
# List privileged apps
adb shell pm list packages -3
# Check /system/app and /system/priv-app
adb shell ls -la /system/app/
adb shell ls -la /system/priv-app/
Permission Analysis for System Apps
# Check if system app has excessive permissions
adb shell dumpsys package <system-package> | grep -A 100 "requested permissions"
# Look for apps with root-level permissions
grep -r "android.permission.*ROOT\|android.permission.*SYSTEM" decompiled/AndroidManifest.xml
Digital Signature Analysis
Certificate Extraction
# Extract certificate from APK
unzip -p base.apk META-INF/CERT.RSA > cert.pem
# View certificate details
keytool -printcert -file cert.pem
# Check signing key
apksigner verify --print-certs base.apk
Signature Verification
# Verify APK signature
apksigner verify base.apk
# Check for multiple signatures (indicates tampering)
keytool -printcert -jarfile base.apk
Common Vulnerability Patterns
1. Exported Components Without Permission
<!-- VULNERABLE: Exported without permission -->
<activity android:name=".SensitiveActivity" android:exported="true" />
<!-- SECURE: Exported with permission -->
<activity android:name=".SensitiveActivity"
android:exported="true"
android:permission="com.example.CUSTOM_PERMISSION" />
2. Weak Intent Filter Validation
// VULNERABLE: Weak validation
if (uri.toString().contains("myapp://")) {
// Process intent
}
// SECURE: Strict validation
if (uri.getScheme().equals("myapp") &&
uri.getHost().equals("secure")) {
// Process intent
}
3. Insecure Content Provider
<!-- VULNERABLE: No write permission -->
<provider android:name=".MyProvider"
android:exported="true"
android:readPermission="com.example.READ"
android:writePermission="" />
<!-- SECURE: Both permissions defined -->
<provider android:name=".MyProvider"
android:exported="true"
android:readPermission="com.example.READ"
android:writePermission="com.example.WRITE" />
4. Sticky Broadcasts
// VULNERABLE: Sticky broadcast (deprecated, data sniffable)
sendStickyBroadcast(intent);
// SECURE: Use LocalBroadcastManager
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
Testing Workflow
Phase 1: Reconnaissance
- Pull APK from device
- Decompile with apktool
- Analyze AndroidManifest.xml
- List all exported components
- Document permissions
Phase 2: Component Testing
- Test each exported Activity with various intents
- Test each exported Service
- Test each exported Broadcast Receiver
- Test each Content Provider
Phase 3: Deep Link Testing
- Enumerate all custom schemes
- Test each scheme with various payloads
- Check for open redirects
- Test for auth bypass
- Test WebView injection
Phase 4: AIDL/Binder Testing
- List all running services
- PING each service to get interface
- Brute-force transaction codes
- Map methods via onTransact()
- Test for missing permission checks
Phase 5: Reporting
- Document all findings
- Provide PoC for each vulnerability
- Suggest remediation steps
- Prioritize by severity
Tools Reference
| Tool | Purpose | Command |
|---|---|---|
apktool |
APK decompilation | apktool d app.apk -o out/ |
dex2jar |
DEX to JAR conversion | dex2jar classes.dex |
jadx |
DEX to Java decompilation | jadx -d out/ app.apk |
adb |
Android Debug Bridge | adb shell |
am |
Activity Manager | am start -a ACTION |
service |
Service management | service list |
content |
Content provider access | content query --uri |
Deep-C |
Deep link automation | deep-C --apk app.apk |
binder-scanner |
AIDL service scanning | python binder-scanner.py |
Security Checklist
- All exported components have appropriate permissions
- Intent filters use strict validation
- No sticky broadcasts in use
- Content providers have both read and write permissions
- WebView has JavaScript disabled (if not needed)
- WebView has file access disabled
- No hardcoded secrets in code
- Proper certificate pinning for network calls
- Sensitive data encrypted at rest
- No debug mode enabled in production