Sandboxing — el pilar fundamental
Android asigna a cada app un UID único de Linux al instalarla. El kernel garantiza que los procesos de diferentes apps no puedan acceder a la memoria ni a los archivos de otras apps. Esta es la primera y más sólida barrera de seguridad.
El resultado práctico: incluso si una app maliciosa se instala en el dispositivo, no puede leer los datos de tu app bancaria, tu historial de mensajes ni tus fotos — a menos que haya una vulnerabilidad en el kernel o en el sistema de archivos.
# Cada app tiene su propio UID:
# u0_a123 → com.ejemplo.miapp
# u0_a124 → com.banco.app
# u0_a125 → com.red.social
# Los archivos de cada app son propiedad de su UID:
ls -la /data/data/
# drwx------ u0_a123 u0_a123 com.ejemplo.miapp/
# drwx------ u0_a124 u0_a124 com.banco.app/
# Solo el propio proceso (o root) puede leer estos directorios
Modelo de permisos
Los permisos en Android son contratos declarados en el Manifest. Hay tres niveles:
- Normal: se otorgan automáticamente sin preguntarle al usuario. Bajo riesgo (INTERNET, VIBRATE, SET_ALARM).
- Dangerous: el usuario debe aprobarlos en runtime. Acceden a datos sensibles (cámara, contactos, ubicación, micrófono, almacenamiento).
- Signature: solo se otorgan a apps firmadas con el mismo keystore. Usados por apps del sistema y grupos de apps del mismo desarrollador.
Declarar no es tenerDeclarar un permiso en el Manifest no garantiza tenerlo. Los permisos "dangerous" hay que pedirlos en runtime y el usuario puede denegarlos. Siempre verificá con checkSelfPermission() antes de usarlos.
Almacenamiento aislado (Scoped Storage)
Desde Android 10, las apps tienen acceso limitado al almacenamiento externo:
- Almacenamiento interno (
filesDir,cacheDir): privado a la app. Nadie más puede leerlo (salvo root o el propio sistema en backups). - Almacenamiento externo propio (
getExternalFilesDir()): accesible sin permiso, pero solo por la propia app. - MediaStore: acceso a fotos, videos y audio del usuario a través de APIs controladas.
- Documentos externos: requiere que el usuario elija explícitamente con el picker del sistema.
// Almacenamiento interno — privado, seguro, sin permisos
val archivo = File(filesDir, "datos_sensibles.json")
// NO usar getExternalStorageDirectory() — deprecated y accesible por otras apps
// NO guardar datos sensibles en el almacenamiento externo
Qué protege el SO (y qué no)
El SO de Android protege:
- Aislamiento entre apps (sandboxing)
- Comunicación entre procesos controlada (Binder IPC)
- Arranque verificado (Verified Boot) — integridad del SO en el arranque
- Cifrado del dispositivo (Full-disk o File-Based Encryption)
Lo que no protege automáticamente y es responsabilidad del desarrollador:
- Datos en tránsito — vos debés usar HTTPS y validarlo correctamente
- Datos en reposo sensibles dentro del almacenamiento interno — el SO los aísla pero no los cifra
- Tokens y contraseñas en SharedPreferences en texto plano
- Logs que contienen información sensible
- Claves hardcodeadas en el código fuente
- Comportamiento en dispositivos rooteados
Las amenazas más comunes
# 1. Datos sensibles en texto plano
# Token de sesión guardado en SharedPreferences sin cifrar
# → EncryptedSharedPreferences (lección 03)
# 2. Tráfico HTTP o HTTPS mal validado
# Man-in-the-middle con cert falso en redes corporativas/cafés
# → Network Security Config + Certificate Pinning (lecciones 04 y 05)
# 3. Información sensible en logs
# Log.d("TOKEN", token) ← visible en adb logcat
# → Nunca loggear datos sensibles, deshabilitar logs en release
# 4. Backup automático de datos sensibles
# Por default Android incluye filesDir en el backup de Google
# → Configurar android:allowBackup y android:fullBackupContent
# 5. Claves hardcodeadas
# val API_KEY = "sk-1234..." ← visible con strings en el APK
# → Variables de entorno en build, no en código
# 6. Contenido de Activity expuesto
# android:exported="true" sin restricciones
# → Revisar exported en el Manifest
Defensa en capas
La seguridad real no viene de una sola medida — viene de capas. Si una falla, las otras siguen protegiendo:
# Capa 1: HTTPS + Certificate Pinning
# → Protege datos en tránsito
# Capa 2: EncryptedSharedPreferences + EncryptedFile
# → Protege datos sensibles en reposo
# Capa 3: Keystore para claves criptográficas
# → Las claves nunca salen del hardware seguro
# Capa 4: Detección de root/emulador
# → Reduce la superficie de ataque
# Capa 5: ProGuard/R8 + anti-tampering
# → Dificulta el reverse engineering
# Ninguna capa es infalible sola.
# La combinación es lo que hace una app segura.