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.
Dónde guarda cada plataforma
Sección titulada «Dónde guarda cada plataforma»Android
Sección titulada «Android»/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)Acceso a los datos (Android)
Sección titulada «Acceso a los datos (Android)»# con root o run-as (si la app es debuggable)adb shell run-as com.target cat /data/data/com.target/shared_prefs/prefs.xmladb shell "su -c 'ls -la /data/data/com.target/'"# bases de datosadb 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)# Objectionandroid keystore list ; android hooking ... # inspeccionarAcceso a los datos (iOS)
Sección titulada «Acceso a los datos (iOS)»# con jailbreak, SSH al dispositivo o Objectionobjection -g com.target.app exploreios keychain dump # volcado del Keychainenv # rutas del contenedor de la appls /var/mobile/Containers/Data/Application/<UUID>/# .plist de NSUserDefaults, SQLite, cachéQué buscar
Sección titulada «Qué buscar»tokens de sesión / JWT, contraseñas, API keys, PINsclaves 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é, logsgrep -riE 'token|password|secret|key|BEGIN' /data/data/com.target/Fugas menos obvias
Sección titulada «Fugas menos obvias»# logs: la app escribe datos sensibles en logcat / NSLogadb 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 sensiblesPara la defensa
Sección titulada «Para la defensa»- 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.
Checklist de prueba
Sección titulada «Checklist de prueba»- 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)