Back to Attack Flows

Table of Contents

What is Insecure Data Storage?

Insecure Data Storage occurs when sensitive information is stored without adequate protection, making it accessible to unauthorized parties. This vulnerability affects applications, databases, file systems, cloud storage, and mobile devices. When data is improperly secured, attackers can:

Why is it Critical?

Insecure Data Storage is a persistent vulnerability in the OWASP Mobile Top 10 (#2 in 2024) and contributes to various OWASP Web Top 10 categories. It's critical because:

How Insecure Data Storage Works

Common Storage Vulnerabilities

1. Plaintext Password Storage

Storing passwords without hashing or encryption:

# ❌ VULNERABLE: Plaintext storage
def create_user(username, password):
    db.execute("INSERT INTO users (username, password) VALUES (?, ?)", 
               (username, password))  # Password stored as plain text!

# ❌ VULNERABLE: Simple encoding is NOT encryption
import base64
encoded = base64.b64encode(password.encode())  # Easily reversed!

2. Weak Encryption

Using outdated or broken encryption algorithms:

# ❌ VULNERABLE: Using DES (deprecated)
from Crypto.Cipher import DES
cipher = DES.new(key, DES.MODE_ECB)  # ECB mode is insecure!

# ❌ VULNERABLE: Hardcoded encryption key
SECRET_KEY = "my_secret_key_123"  # Key in source code!

3. Insecure Local Storage

Mobile and web applications storing sensitive data insecurely:

// ❌ VULNERABLE: Web browser localStorage (not encrypted)
localStorage.setItem('authToken', token);
localStorage.setItem('creditCard', cardNumber);

// ❌ VULNERABLE: Mobile app shared preferences (plaintext)
SharedPreferences prefs = context.getSharedPreferences("MyApp", MODE_PRIVATE);
prefs.edit().putString("password", userPassword).commit();

4. Exposed Backup Files

Database backups left accessible:

# Attackers look for backup files:
database.sql.bak
users.db.old
backup_2024.sql
db_dump.sql
.git/config  # Git repositories with sensitive data

Attack Vectors

1. File System Access

2. Cloud Misconfigurations

# ❌ VULNERABLE: Public S3 bucket
aws s3 ls s3://company-backups --no-sign-request
# Returns: database-backup-2024.sql

# ❌ VULNERABLE: Azure blob with public access
https://mystorageaccount.blob.core.windows.net/backups/users.db

3. Memory Dumps

Extracting data from application memory:

# Android memory dump
adb shell
run-as com.vulnerable.app
cat /data/data/com.vulnerable.app/databases/users.db

Advanced Attack Techniques

1. Mobile Data Extraction

Android Exploitation

# Extract app data (rooted device)
adb root
adb pull /data/data/com.example.app/

# SQLite database extraction
adb pull /data/data/com.example.app/databases/userdata.db
sqlite3 userdata.db "SELECT * FROM users;"

# Shared preferences (XML files with plaintext data)
adb pull /data/data/com.example.app/shared_prefs/
cat *.xml

iOS Exploitation

# Jailbroken iOS device
ssh root@device-ip
cd /var/mobile/Containers/Data/Application/[APP-ID]/

# Keychain extraction (if improperly protected)
keychain_dumper -a

# NSUserDefaults (plist files)
plutil -p Library/Preferences/com.example.app.plist

2. Cloud Storage Enumeration

AWS S3 Bucket Discovery

# Common bucket naming patterns
aws s3 ls s3://companyname-backups --no-sign-request
aws s3 ls s3://companyname-prod --no-sign-request
aws s3 ls s3://companyname-data --no-sign-request

# Automated enumeration
bucket_finder.py companyname wordlist.txt

# Download exposed data
aws s3 sync s3://exposed-bucket ./ --no-sign-request

Azure Storage Exploitation

# Enumerate containers
https://[account].blob.core.windows.net/[container]?restype=container&comp=list

# Access public blobs
https://mystorageaccount.blob.core.windows.net/backups/?comp=list

3. Database File Extraction

SQLite Database Analysis

# Open database
sqlite3 app_database.db

# List tables
.tables

# Extract user credentials
SELECT username, password, email FROM users;

# Check for encryption
PRAGMA cipher_version;  # If empty, database is unencrypted

# Recover deleted data
SELECT * FROM users WHERE rowid NOT IN (SELECT rowid FROM users);

Configuration File Parsing

# Search for credentials in config files
grep -r "password" /path/to/app/
grep -r "api_key" /path/to/app/
grep -r "secret" /path/to/app/

# Common credential patterns
grep -rE "(password|passwd|pwd|api_key|secret_key|access_token)" .

4. Log File Mining

# ❌ VULNERABLE: Logging sensitive data
import logging

logging.info(f"User login: username={username}, password={password}")
logging.debug(f"API request with token: {auth_token}")
logging.error(f"Database connection failed: {connection_string}")
# All of this ends up in log files accessible to attackers!

5. Cache Exploitation

# Browser cache
~/.cache/google-chrome/Default/Cache/
~/Library/Caches/  # macOS

# Application cache
/data/data/com.example.app/cache/  # Android
/var/mobile/Containers/Data/Application/[ID]/Library/Caches/  # iOS

# Search cache for sensitive data
grep -r "password\|credit\|ssn\|token" cache_directory/

Defense Bypass Strategies

Bypassing Basic Obfuscation

1. Base64 Decoding

# "Encrypted" with base64 (not real encryption!)
import base64

# Attacker simply decodes:
encoded_password = "cGFzc3dvcmQxMjM="
decoded = base64.b64decode(encoded_password).decode()
# Result: "password123"

2. ROT13 / Simple Ciphers

# Simple rotation cipher
import codecs

# Easily reversed:
obfuscated = "frperg_cnffjbeq"
revealed = codecs.decode(obfuscated, 'rot_13')
# Result: "secret_password"

3. XOR with Static Key

# XOR with hardcoded key (reversible)
def xor_decrypt(encrypted, key):
    return ''.join(chr(c ^ ord(key[i % len(key)])) 
                   for i, c in enumerate(encrypted))

# Attacker extracts key from app code and decrypts

Extracting Hardcoded Keys

Reverse Engineering Mobile Apps

# Decompile Android APK
apktool d application.apk
jadx application.apk

# Search for keys in decompiled code
grep -r "AES\|DES\|KEY\|SECRET" .
grep -r "0x[0-9a-fA-F]\{32,\}" .  # Hex keys

# iOS binary analysis
class-dump application.app/application
strings application | grep -i "key\|secret\|password"

Bypassing File Permissions

Android Permission Escalation

# Backup extraction (no root needed)
adb backup -f backup.ab -noapk com.example.app
dd if=backup.ab bs=24 skip=1 | openssl zlib -d > backup.tar
tar -xvf backup.tar

# Exploit world-readable files
adb shell
run-as com.example.app
ls -la  # Check file permissions
cat databases/sensitive.db  # If readable

Cloud Storage Enumeration Techniques

Brute Force Bucket Names

# Common patterns for bucket discovery
company-name-prod
company-name-backup
company-name-data
companyname-logs
www-companyname-com

# Automated tools
cloud_enum.py -k company-name
s3scanner scan -b bucket-wordlist.txt

Prevention & Mitigation

1. Strong Password Storage (Hashing)

THE PRIMARY DEFENSE FOR PASSWORDS

# ✅ GOOD: Using bcrypt (Python)
import bcrypt

# Hash password
password = "user_password"
salt = bcrypt.gensalt(rounds=12)  # Cost factor
hashed = bcrypt.hashpw(password.encode(), salt)

# Verify password
if bcrypt.checkpw(password.encode(), hashed):
    print("Password correct!")
# ✅ GOOD: Using Argon2 (recommended)
from argon2 import PasswordHasher

ph = PasswordHasher()
hash = ph.hash("user_password")

# Verify
try:
    ph.verify(hash, "user_password")
    print("Password correct!")
except:
    print("Wrong password")
// ✅ GOOD: Using bcrypt (Java)
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);
String hashedPassword = encoder.encode("user_password");

// Verify
boolean matches = encoder.matches("user_password", hashedPassword);

2. Proper Encryption Implementation

✅ Using AES-256 Correctly

# ✅ GOOD: AES-256-GCM with proper key derivation
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os

# Derive key from password
kdf = PBKDF2HMAC(
    algorithm=hashes.SHA256(),
    length=32,
    salt=os.urandom(16),
    iterations=100000,
)
key = kdf.derive(b"user_password")

# Encrypt with AES-GCM (authenticated encryption)
iv = os.urandom(12)
cipher = Cipher(algorithms.AES(key), modes.GCM(iv))
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
tag = encryptor.tag  # Authentication tag

3. Secure Key Management

Environment Variables (Better than Hardcoding)

# ✅ GOOD: Key from environment
import os

ENCRYPTION_KEY = os.environ.get('ENCRYPTION_KEY')
if not ENCRYPTION_KEY:
    raise ValueError("ENCRYPTION_KEY not set!")

Hardware Security Modules (HSM) / Key Management Systems

# ✅ BEST: Using AWS KMS
import boto3

kms = boto3.client('kms')

# Encrypt data
response = kms.encrypt(
    KeyId='arn:aws:kms:region:account:key/key-id',
    Plaintext=sensitive_data
)
ciphertext = response['CiphertextBlob']

# Decrypt data
response = kms.decrypt(CiphertextBlob=ciphertext)
plaintext = response['Plaintext']

Mobile Keychain / Keystore

// ✅ GOOD: Android Keystore
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;

KeyGenerator keyGen = KeyGenerator.getInstance(
    KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

keyGen.init(new KeyGenParameterSpec.Builder(
    "MyKeyAlias",
    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
    .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
    .setUserAuthenticationRequired(true)
    .build());

SecretKey key = keyGen.generateKey();
// ✅ GOOD: iOS Keychain
import Security

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "userToken",
    kSecValueData as String: tokenData,
    kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]

SecItemAdd(query as CFDictionary, nil)

4. Secure Cloud Storage Configuration

AWS S3 Security

// ✅ GOOD: S3 bucket policy (block public access)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::my-bucket/*",
        "arn:aws:s3:::my-bucket"
      ],
      "Condition": {
        "Bool": {
          "aws:SecureTransport": "false"
        }
      }
    }
  ]
}
# ✅ Enable S3 encryption
aws s3api put-bucket-encryption \
  --bucket my-bucket \
  --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

# ✅ Block public access
aws s3api put-public-access-block \
  --bucket my-bucket \
  --public-access-block-configuration \
  "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

5. Secure Mobile Storage

iOS: Use Data Protection API

// ✅ GOOD: File protection
let data = sensitiveData.data(using: .utf8)!
try data.write(to: fileURL, options: .completeFileProtection)

Android: Use EncryptedSharedPreferences

// ✅ GOOD: Encrypted shared preferences
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKey;

MasterKey masterKey = new MasterKey.Builder(context)
    .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
    .build();

SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
    context,
    "secret_shared_prefs",
    masterKey,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

sharedPreferences.edit().putString("token", authToken).apply();

6. Secure Data Deletion

# ✅ GOOD: Secure file deletion
import os

def secure_delete(filepath):
    # Overwrite file multiple times before deletion
    length = os.path.getsize(filepath)
    with open(filepath, 'br+') as f:
        for _ in range(3):
            f.seek(0)
            f.write(os.urandom(length))
    os.remove(filepath)

7. Avoid Logging Sensitive Data

# ❌ BAD
logging.info(f"User {username} logged in with password {password}")

# ✅ GOOD
logging.info(f"User {username} logged in successfully")

# ✅ GOOD: Redact sensitive data
def redact_sensitive(data):
    return data[:4] + "****" + data[-4:] if len(data) > 8 else "****"

logging.info(f"Processing card {redact_sensitive(card_number)}")

8. Database Encryption

SQLite Encryption

# ✅ GOOD: SQLCipher for encrypted SQLite
import sqlcipher3 as sqlite3

conn = sqlite3.connect('encrypted.db')
conn.execute("PRAGMA key='your-encryption-key'")
conn.execute("PRAGMA cipher_page_size=4096")

Transparent Data Encryption (TDE)

-- ✅ SQL Server TDE
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'StrongPassword123!';
CREATE CERTIFICATE TDECert WITH SUBJECT = 'TDE Certificate';

USE MyDatabase;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDECert;

ALTER DATABASE MyDatabase SET ENCRYPTION ON;

Detection & Testing

Manual Testing Techniques

1. Mobile App Analysis

# Android - Extract and analyze APK
apktool d app.apk
jadx app.apk -d output_dir

# Search for insecure storage
grep -r "SharedPreferences" output_dir/
grep -r "MODE_WORLD_READABLE\|MODE_WORLD_WRITABLE" output_dir/
grep -r "openFileOutput.*MODE_WORLD" output_dir/

# Check for hardcoded secrets
grep -ri "password\|secret\|api_key\|token" output_dir/
grep -rE "[A-Za-z0-9]{32,}" output_dir/  # Potential keys

# iOS - Analyze app bundle
class-dump App.app/App > headers.txt
strings App.app/App | grep -i "password\|secret\|key"
otool -L App.app/App  # Check for security frameworks

2. Database Security Check

# Check SQLite encryption
sqlite3 database.db
PRAGMA cipher_version;

# If no output, database is UNENCRYPTED!
# Check for sensitive data
.tables
SELECT * FROM users LIMIT 5;
SELECT * FROM credentials LIMIT 5;

3. File Permission Audit

# Android device
adb shell
run-as com.example.app
ls -la databases/
ls -la shared_prefs/
# Check for world-readable (r--r--r--) files

# Look for backup files
find /data/data/com.example.app/ -name "*.bak"
find /data/data/com.example.app/ -name "*.old"

4. Cloud Storage Enumeration

# Test S3 bucket permissions
aws s3 ls s3://target-bucket --no-sign-request

# Test public access
curl https://target-bucket.s3.amazonaws.com/

# Azure storage
curl "https://account.blob.core.windows.net/container/?restype=container&comp=list"

Automated Testing Tools

Mobile Security Scanners

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

# Upload APK/IPA and scan for:
# - Insecure storage
# - Hardcoded secrets
# - Weak encryption
# - Improper file permissions

# Drozer (Android)
drozer console connect
run app.package.info -a com.example.app
run app.provider.finduri com.example.app
run scanner.provider.finduris -a com.example.app

Static Analysis Tools

# Trufflehog - Find secrets in code
trufflehog filesystem /path/to/code --json

# GitLeaks - Detect secrets in Git repos
gitleaks detect --source /path/to/repo

# Semgrep - Pattern-based code scanner
semgrep --config=p/owasp-top-ten /path/to/code

# Custom grep patterns
grep -rE "(password|passwd|pwd|api_key|secret|token)\s*=\s*['\"][^'\"]{8,}" .

Cloud Security Scanners

# ScoutSuite - Multi-cloud security auditing
scout aws --profile myprofile

# Prowler - AWS security assessment
prowler aws -M csv,html

# CloudSploit - Cloud security scanning
./index.js --cloud aws --config config.json

Code Review Checklist

# Search for vulnerable patterns

# Plaintext password storage
grep -r "password.*=.*request\|request.*password" .
grep -r "INSERT.*password.*VALUES" .

# Weak encryption
grep -ri "DES\|RC4\|MD5\|SHA1" .
grep -r "MODE_ECB" .

# Hardcoded secrets
grep -rE "(api_key|secret|password)\s*=\s*['\"][^'\"]{8,}" .
grep -rE "['\"][A-Za-z0-9+/]{40,}={0,2}['\"]" .  # Base64 secrets

# Insecure storage
grep -r "localStorage.setItem" .  # Web
grep -r "SharedPreferences.*MODE_WORLD" .  # Android
grep -r "NSUserDefaults.*string" .  # iOS (check if encrypted)

# Logging sensitive data
grep -r "log.*password\|log.*token\|log.*secret" .

Real-World Examples

Notable Breaches

1. Adobe (2013) [VERIFY SOURCE]

2. LinkedIn (2012) [VERIFY SOURCE]

3. Capital One (2019) [VERIFY SOURCE]

4. Uber (2016) [VERIFY SOURCE]

5. Facebook (2019 - Plaintext Passwords) [VERIFY SOURCE]

6. T-Mobile (2021) [VERIFY SOURCE]

Common Vulnerable Scenarios

Quick Reference

Common Vulnerable Patterns

# ❌ Plaintext password storage
password = request.form['password']
db.execute("INSERT INTO users (password) VALUES (?)", (password,))

# ❌ Weak hashing (MD5/SHA1)
import hashlib
hashed = hashlib.md5(password.encode()).hexdigest()

# ❌ Hardcoded encryption key
KEY = "my_secret_key_1234567890123456"

# ❌ Insecure local storage
localStorage.setItem('authToken', token);

# ❌ World-readable files (Android)
openFileOutput("data.txt", MODE_WORLD_READABLE);

# ❌ Logging sensitive data
logging.info(f"Password: {password}, Token: {token}")

Secure Implementation Examples

# ✅ Proper password hashing (Argon2)
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash(password)

# ✅ Secure encryption (AES-256-GCM)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)

# ✅ Environment-based secrets
import os
SECRET_KEY = os.environ['SECRET_KEY']

# ✅ Secure mobile storage (Android)
import androidx.security.crypto.EncryptedSharedPreferences

# ✅ Secure keychain (iOS)
kSecAttrAccessibleWhenUnlockedThisDeviceOnly

# ✅ Secure cloud storage (S3)
BlockPublicAccess=true, ServerSideEncryption=AES256

Testing Checklist

Prevention Checklist

Encryption Algorithm Selection

✅ RECOMMENDED

  • Password Hashing: Argon2id, bcrypt (cost ≥ 12), PBKDF2 (≥ 100,000 iterations)
  • Symmetric Encryption: AES-256-GCM, ChaCha20-Poly1305
  • Key Derivation: PBKDF2, Argon2, scrypt
  • Random Generation: os.urandom(), SecureRandom (Java), CryptoKit (iOS)

❌ AVOID / DEPRECATED

  • DO NOT USE: DES, 3DES, RC4, MD5, SHA1 (for passwords)
  • DO NOT USE: ECB mode (reveals patterns)
  • DO NOT USE: Base64 encoding (not encryption!)
  • DO NOT USE: Plaintext, ROT13, simple XOR

Resources