Saltearse al contenido

Almacenamiento inseguro

Una de las clases de fallos más comunes y fáciles de encontrar en apps móviles es guardar datos sensibles —tokens, contraseñas, claves, PII, información de sesión— en el dispositivo sin cifrar o en lugares accesibles. Como el dispositivo puede estar rooteado/jailbroken (o respaldado), todo lo que la app escriba en claro queda expuesto. Es la categoría MASVS-STORAGE y casi siempre produce hallazgos.

/data/data/<paquete>/
shared_prefs/*.xml SharedPreferences (clave-valor, a menudo en claro)
databases/*.db SQLite (datos de la app)
files/ ficheros internos
cache/ caché
# almacenamiento externo (accesible por otras apps / sin sandbox fuerte)
/sdcard/Android/data/<paquete>/
# el lugar correcto para secretos:
Android Keystore claves respaldadas por hardware (TEE/StrongBox)
/var/mobile/Containers/Data/Application/<UUID>/
Library/Preferences/*.plist NSUserDefaults (clave-valor, en claro)
Documents/, Library/, tmp/ ficheros, SQLite, caché
# el lugar correcto para secretos:
Keychain almacén cifrado del sistema (con clases de protección)
# con root o run-as (si la app es debuggable)
adb shell run-as com.target cat /data/data/com.target/shared_prefs/prefs.xml
adb shell "su -c 'ls -la /data/data/com.target/'"
# bases de datos
adb pull /data/data/com.target/databases/app.db ; sqlite3 app.db
# backup (si allowBackup=true, sin root)
adb backup -f backup.ab com.target ; (abe.jar para extraer)
# Objection
android keystore list ; android hooking ... # inspeccionar
# con jailbreak, SSH al dispositivo o Objection
objection -g com.target.app explore
ios keychain dump # volcado del Keychain
env # rutas del contenedor de la app
ls /var/mobile/Containers/Data/Application/<UUID>/
# .plist de NSUserDefaults, SQLite, caché
tokens de sesión / JWT, contraseñas, API keys, PINs
claves de cifrado guardadas junto a los datos cifrados (error clásico)
PII (datos personales), datos de tarjetas, mensajes
# en cualquier formato: SharedPreferences/plist, SQLite, ficheros, caché, logs
grep -riE 'token|password|secret|key|BEGIN' /data/data/com.target/
# logs: la app escribe datos sensibles en logcat / NSLog
adb logcat | grep -i target
# caché de teclado, pasteboard (iOS), capturas en background (snapshot al minimizar)
# WebView cache, datos en memoria no limpiados
# backups en la nube (iCloud/Google Backup) incluyendo datos sensibles
  • Secretos en el almacén seguro: Android Keystore / iOS Keychain (con clase de protección adecuada), nunca en SharedPreferences/NSUserDefaults/ficheros en claro.
  • No guardar lo que no haga falta: minimizar datos en el dispositivo; tokens de vida corta.
  • Cifrado correcto: no almacenar la clave junto al dato; usar claves no extraíbles (hardware-backed).
  • allowBackup=false (Android), excluir datos sensibles de los backups; Data Protection (iOS).
  • No loguear datos sensibles; limpiar caché/pasteboard; proteger la captura en background.
  • Localizar los directorios de datos de la app (Android/iOS)
  • SharedPreferences / NSUserDefaults en claro
  • Bases de datos SQLite con datos sensibles
  • Ficheros, caché y almacenamiento externo
  • Keystore/Keychain: ¿se usan? ¿clase de protección?
  • Claves de cifrado guardadas junto a los datos
  • Fugas en logs, pasteboard, capturas en background, backups
  • allowBackup/backup extraíble (Android)