Data Security
Intermediate

Insecure Local Storage

Mobile apps frequently store sensitive data locally without proper encryption. This guide covers identifying and exploiting insecure data storage on both Android and iOS platforms.

OWASP M2: Insecure Data Storage

Insecure data storage is the #2 risk in the OWASP Mobile Top 10. Sensitive data stored in plaintext or with weak encryption can be extracted from lost/stolen devices, malware, or forensic analysis.

Android Storage Locations

SharedPreferences

XML files storing key-value pairs. Often contain tokens, credentials, and settings:

bash
# Location on device
/data/data/<package>/shared_prefs/

# List all SharedPreferences files
adb shell run-as com.target.app ls shared_prefs/

# Read preferences (rooted device)
adb shell cat /data/data/com.target.app/shared_prefs/*.xml

# Using Frida to dump SharedPreferences
Java.perform(function() {
    var context = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
    var prefs = context.getSharedPreferences("app_prefs", 0);
    var all = prefs.getAll();
    var it = all.entrySet().iterator();
    while (it.hasNext()) {
        var entry = it.next();
        console.log(entry.getKey() + ": " + entry.getValue());
    }
});

SQLite Databases

Local databases often store user data, messages, and cached content:

bash
# Database location
/data/data/<package>/databases/

# Pull database
adb shell run-as com.target.app cat databases/app.db > app.db

# Or on rooted device
adb pull /data/data/com.target.app/databases/app.db

# Analyze with SQLite
sqlite3 app.db
.tables
.schema users
SELECT * FROM users;

# Look for sensitive data
SELECT * FROM sqlite_master WHERE type='table';

Internal Files

bash
# Internal storage location
/data/data/<package>/files/
/data/data/<package>/cache/

# List all files
adb shell run-as com.target.app find . -type f

# Search for sensitive patterns
adb shell run-as com.target.app grep -r "password|token|key|secret" files/

# Check file permissions
adb shell run-as com.target.app ls -la files/

External Storage (World-Readable)

High Risk

Data stored on external storage (SD card) is readable by any app with storage permissions.
bash
# External storage locations
/sdcard/
/sdcard/Android/data/<package>/

# Search for app data
adb shell find /sdcard -name "*target*" 2>/dev/null

# Check for exported files
adb shell ls -la /sdcard/Android/data/com.target.app/

iOS Storage Locations

Keychain

iOS secure storage. Can be dumped on jailbroken devices:

bash
# Using keychain-dumper (on device)
./keychain-dumper

# Using Objection
objection -g com.target.app explore
ios keychain dump

# Using Frida
ObjC.schedule(ObjC.mainQueue, function() {
    var query = ObjC.classes.NSMutableDictionary.alloc().init();
    query.setObject_forKey_(ObjC.classes.kSecClassGenericPassword, "class");
    query.setObject_forKey_(ObjC.classes.kSecMatchLimitAll, "limit");
    query.setObject_forKey_(true, "returnData");
    
    var result = ObjC.classes.SecItemCopyMatching(query, null);
    console.log(result);
});

NSUserDefaults / Plist Files

bash
# Plist locations
/var/mobile/Containers/Data/Application/<UUID>/Library/Preferences/

# Read plist files
plutil -p /path/to/com.target.app.plist

# Using Objection
ios plist cat com.target.app.plist

# Frida to dump NSUserDefaults
Java.perform(function() {
    var NSUserDefaults = ObjC.classes.NSUserDefaults;
    var defaults = NSUserDefaults.standardUserDefaults();
    var dict = defaults.dictionaryRepresentation();
    console.log(dict.toString());
});

SQLite & Core Data

bash
# Database locations
/var/mobile/Containers/Data/Application/<UUID>/Documents/
/var/mobile/Containers/Data/Application/<UUID>/Library/

# Find all databases
find /var/mobile/Containers/Data/Application/<UUID> -name "*.sqlite" -o -name "*.db"

# Copy to computer
scp root@device:/path/to/database.sqlite .

# Analyze
sqlite3 database.sqlite
.tables
SELECT * FROM sensitive_table;

Cache & Cookies

bash
# Cache locations
/var/mobile/Containers/Data/Application/<UUID>/Library/Caches/

# Cookies database
/var/mobile/Containers/Data/Application/<UUID>/Library/Cookies/Cookies.binarycookies

# Using Objection
ios cookies get

# Check for sensitive cached data
find /var/mobile/Containers/Data/Application/<UUID>/Library/Caches -type f -exec file {} \;

Automated Analysis

Android - Objection Commands

bash
# Explore the app
objection -g com.target.app explore

# List files in app directory
env
android root disable  # If needed

# SQLite commands
sqlite connect app.db
sqlite execute query SELECT * FROM users;

# Monitor file system access
android filesystem watch /data/data/com.target.app/

iOS - Objection Commands

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

# Environment info
env

# Dump keychain
ios keychain dump

# Get cookies
ios cookies get

# List bundles
ios bundles list

# Dump NSUserDefaults
ios nsuserdefaults get

Security Comparison

Storage Encrypted Accessible Risk
Android Keystore Yes (hardware-backed) Root + app context Low
iOS Keychain Yes (SEP) Jailbreak + tools Low
SharedPreferences No (plaintext XML) Root or backup Medium
NSUserDefaults No (plaintext plist) Jailbreak or backup Medium
SQLite No (unless SQLCipher) Root/jailbreak Medium
External Storage No Any app High

Sensitive Data to Find

Authentication Data

  • • Usernames and passwords
  • • Session tokens / JWT
  • • API keys
  • • OAuth tokens
  • • Remember me tokens

Personal Information

  • • Names, emails, phone numbers
  • • Credit card data
  • • Health information
  • • Location history
  • • Private messages

Cryptographic Material

  • • Private keys
  • • Encryption keys
  • • Certificates
  • • Encryption IVs

Application Data

  • • Backend URLs
  • • Debug flags
  • • Feature toggles
  • • Internal IDs

Reporting Findings

When reporting insecure storage issues, include: the exact file/database location, what sensitive data was found, how it could be accessed (root vs non-root), and the potential impact of exposure.