La plataforma de Android aprovecha la protección basada en el usuario de Linux para identificar y aislar los recursos de la app. Esto aísla las apps entre sí y protege a las apps y al sistema de las apps maliciosas. Para ello, Android asigna un ID de usuario único (UID) a cada app para Android y la ejecuta en su propio proceso.
Android usa el UID para configurar una zona de pruebas de aplicaciones a nivel del kernel. El kernel aplica la seguridad entre las apps y el sistema a nivel del proceso a través de las funciones estándar de Linux, como los IDs de usuario y de grupo que se asignan a las apps. De forma predeterminada, las apps no pueden interactuar entre sí y tienen acceso limitado al SO. Si la app A intenta hacer algo malicioso, como leer los datos de la app B o marcar el teléfono sin permiso, no puede hacerlo porque no tiene los privilegios de usuario predeterminados adecuados. La zona de pruebas es simple, auditable y se basa en la separación de usuarios de procesos y permisos de archivos al estilo de UNIX, que tiene décadas de antigüedad.
Debido a que la zona de pruebas de aplicaciones está en el kernel, este modelo de seguridad se extiende al código nativo y a las apps del SO. Todo el software por sobre el kernel, como las bibliotecas del SO, el framework de la app, el entorno de ejecución de la app y todas las apps, se ejecuta dentro de la zona de pruebas de aplicaciones. En algunas plataformas, los desarrolladores se ven limitados a un framework de desarrollo, un conjunto de APIs o un lenguaje específicos. En Android, no hay restricciones sobre cómo se puede escribir una app que sean necesarias para aplicar la seguridad. En este sentido, el código nativo está en la zona de pruebas como el código interpretado.
Protecciones
Por lo general, para salir de la zona de pruebas de aplicaciones en un dispositivo configurado correctamente, se debe vulnerar la seguridad del kernel de Linux. Sin embargo, al igual que otras funciones de seguridad, las protecciones individuales que aplican la zona de pruebas de la app no son invulnerables, por lo que la defensa en profundidad es importante para evitar que una sola vulnerabilidad comprometa el SO o otras apps.
Android se basa en una serie de protecciones para aplicar la zona de pruebas de la app. Estas aplicaciones forzosas se introdujeron con el tiempo y fortalecieron significativamente la zona de pruebas de control de acceso discrecional (DAC) basada en UID original. Las versiones anteriores de Android incluían las siguientes protecciónes:
- En Android 5.0, SELinux proporcionaba una separación de control de acceso obligatorio (MAC) entre el sistema y las apps. Sin embargo, todas las apps de terceros se ejecutaban dentro del mismo contexto de SELinux, por lo que el aislamiento entre apps se aplicaba principalmente a través de DAC de UID.
- En Android 6.0, se amplió la zona de pruebas de SELinux para aislar las apps en el límite de cada usuario físico. Además, Android también estableció valores predeterminados más seguros para los datos de la app: en el caso de las apps con
targetSdkVersion >= 24
, los permisos de DAC predeterminados en el directorio principal de una app cambiaron de 751 a 700. Esto proporcionó una configuración predeterminada más segura para los datos privados de la app (aunque las apps pueden anular estos parámetros predeterminados). - En Android 8.0, todas las apps se configuraron para ejecutarse con un filtro
seccomp-bpf
que limitaba las llamadas al sistema que podían usar, lo que fortalecía el límite entre la app y el kernel. - En Android 9, todas las apps sin privilegios con
targetSdkVersion >= 28
deben ejecutarse en zonas de pruebas de SELinux individuales, lo que proporciona MAC por app. Esta protección mejora la separación de apps, evita anular los valores predeterminados seguros y, lo más importante, evita que las apps permitan el acceso a sus datos a todo el mundo. - En Android 10, las apps tienen una vista sin formato limitada del sistema de archivos, sin acceso directo a rutas como /sdcard/DCIM. Sin embargo, las apps conservan el acceso completo sin formato a las rutas específicas de paquetes, como muestra cualquier método aplicable, como Context.getExternalFilesDir().
Lineamientos para compartir archivos
Establecer los datos de la app como accesibles para todo el mundo es una práctica de seguridad deficiente. Se otorga acceso a todos y no es posible limitar el acceso solo a los destinatarios previstos. Esta práctica ha provocado filtraciones de divulgación de información y vulnerabilidades de suplentes confusas, y es un objetivo favorito del software malicioso que se orienta a apps con datos sensibles (como clientes de correo electrónico). En Android 9 y versiones posteriores, no se permite compartir archivos de esta manera de forma explícita para las apps con targetSdkVersion>=28
.
En lugar de permitir que todos puedan acceder a los datos de la app, usa los siguientes lineamientos cuando compartas archivos:
- Si tu app necesita compartir archivos con otra app, usa un proveedor de contenido. Los proveedores de contenido comparten datos con el nivel de detalle adecuado y sin las muchas desventajas de los permisos de UNIX accesibles para todos (para obtener más información, consulta Conceptos básicos sobre proveedores de contenido).
- Si tu app tiene archivos a los que realmente todos deberían poder acceder (como fotos), deben ser específicos de contenido multimedia (solo fotos, videos y archivos de audio) y almacenarse con la clase MediaStore. (Para obtener más detalles sobre cómo agregar un elemento multimedia, consulta Cómo acceder a archivos de contenido multimedia desde el almacenamiento compartido).
El permiso de tiempo de ejecución de Almacenamiento controla el acceso a las colecciones con tipado estricto a través de MediaStore.
Para acceder a archivos con tipado débil, como los archivos PDF y la clase MediaStore.Downloads, las apps deben usar intents como el intent ACTION_OPEN_DOCUMENT
.
Para habilitar el comportamiento de Android 10, usa el atributo del manifiesto requestLegacyExternalStorage
y sigue las prácticas recomendadas de permisos de la app.
- El valor predeterminado de la marca del manifiesto es
true
para las apps orientadas a Android 9 (y versiones anteriores). - El valor predeterminado es "false" para las apps que se orientan a Android 10. Para inhabilitar temporalmente la vista de almacenamiento filtrada en las apps orientadas a Android 10, configura el valor de la marca de manifiesto como
true
. - Con permisos restringidos, el instalador incluye en la lista de entidades permitidas las apps que se permiten para el almacenamiento sin zona de pruebas. Las apps que no están en la lista de entidades permitidas se ejecutan en la zona de pruebas.