Revise esta página para familiarizarse con los conceptos de SELinux.
Control de acceso obligatorio
Security Enhanced Linux (SELinux) es un sistema de control de acceso obligatorio (MAC) para el sistema operativo Linux. Como sistema MAC, difiere del conocido sistema de control de acceso discrecional (DAC) de Linux. En un sistema DAC, existe un concepto de propiedad, mediante el cual el propietario de un recurso en particular controla los permisos de acceso asociados con él. Por lo general, esto es de granularidad gruesa y está sujeto a una escalada de privilegios no intencionada. Sin embargo, un sistema MAC consulta a una autoridad central para tomar una decisión sobre todos los intentos de acceso.
SELinux se ha implementado como parte del marco del módulo de seguridad de Linux (LSM), que reconoce varios objetos del núcleo y acciones confidenciales realizadas en ellos. En el punto en el que se realizaría cada una de estas acciones, se llama a una función de enlace LSM para determinar si la acción debe permitirse o no en función de la información almacenada en un objeto de seguridad opaco. SELinux proporciona una implementación para estos ganchos y la gestión de estos objetos de seguridad, que se combinan con su propia política para determinar las decisiones de acceso.
Junto con otras medidas de seguridad de Android, la política de control de acceso de Android limita en gran medida el daño potencial de las máquinas y cuentas comprometidas. El uso de herramientas como los controles de acceso obligatorios y discrecionales de Android le brinda una estructura para garantizar que su software se ejecute solo con el nivel mínimo de privilegios. Esto mitiga los efectos de los ataques y reduce la probabilidad de que los procesos erróneos sobrescriban o incluso transmitan datos.
En Android 4.3 y superior, SELinux proporciona un paraguas de control de acceso obligatorio (MAC) sobre los entornos tradicionales de control de acceso discrecional (DAC). Por ejemplo, el software generalmente debe ejecutarse como la cuenta de usuario raíz para escribir en dispositivos de bloques sin formato. En un entorno Linux tradicional basado en DAC, si el usuario raíz se ve comprometido, ese usuario puede escribir en cada dispositivo de bloque sin formato. Sin embargo, SELinux se puede usar para etiquetar estos dispositivos, de modo que el proceso al que se le asigne el privilegio de raíz pueda escribir solo en aquellos especificados en la política asociada. De esta forma, el proceso no puede sobrescribir los datos y la configuración del sistema fuera del dispositivo de bloque sin procesar específico.
Consulte Casos de uso para obtener más ejemplos de amenazas y formas de abordarlas con SELinux.
Niveles de cumplimiento
SELinux se puede implementar en varios modos:
- Permisivo : la política de seguridad de SELinux no se aplica, solo se registra.
- Cumplimiento : la política de seguridad se aplica y se registra. Las fallas aparecen como errores EPERM.
Esta opción es binaria y determina si su política toma medidas o simplemente le permite recopilar fallas potenciales. Permisivo es especialmente útil durante la implementación.
Tipos, atributos y reglas
Android se basa en el componente Type Enforcement (TE) de SELinux para su política. Significa que todos los objetos (como archivo, proceso o socket) tienen un tipo asociado con ellos. Por ejemplo, de forma predeterminada, una aplicación tendrá el tipo untrusted_app
. Para un proceso, su tipo también se conoce como su dominio . Es posible anotar un tipo con uno o varios atributos . Los atributos son útiles para hacer referencia a varios tipos al mismo tiempo.
Los objetos se asignan a clases (por ejemplo, un archivo, un directorio, un enlace simbólico, un socket) y los diferentes tipos de acceso para cada clase se representan mediante permisos . Por ejemplo, el permiso open
existe para el file
de clase. Si bien los tipos y atributos se actualizan periódicamente como parte de la política de SELinux de Android, los permisos y las clases se definen de forma estática y rara vez se actualizan como parte de una nueva versión de Linux.
Una regla de política viene en la forma: allow source target : class permissions ;
donde:
- Origen : el tipo (o atributo) del asunto de la regla. ¿Quién solicita el acceso?
- Destino : el tipo (o atributo) del objeto. ¿A qué se solicita el acceso?
- Clase : el tipo de objeto (p. ej., archivo, socket) al que se accede.
- Permisos : la operación (o conjunto de operaciones) (por ejemplo, lectura, escritura) que se está realizando.
Un ejemplo de regla es:
allow untrusted_app app_data_file:file { read write };
Esto dice que las aplicaciones pueden leer y escribir archivos etiquetados como app_data_file
. Existen otros tipos de aplicaciones. Por ejemplo, isolated_app
se usa para servicios de aplicaciones con isolatedProcess=true
en su manifiesto. En lugar de repetir la regla para ambos tipos, Android usa un atributo llamado appdomain
para todos los tipos que cubren las aplicaciones:
# Associate the attribute appdomain with the type untrusted_app. typeattribute untrusted_app, appdomain; # Associate the attribute appdomain with the type isolated_app. typeattribute isolated_app, appdomain; allow appdomain app_data_file:file { read write };
Cuando se escribe una regla que especifica un nombre de atributo, ese nombre se expande automáticamente a la lista de dominios o tipos asociados con el atributo. Algunos atributos notables son:
-
domain
- atributo asociado con todos los tipos de procesos, -
file_type
: atributo asociado con todos los tipos de archivos.
macros
Para el acceso a archivos en particular, hay muchos tipos de permisos a considerar. Por ejemplo, el permiso de read
no es suficiente para abrir el archivo o llamar a stat
sobre él. Para simplificar la definición de la regla, Android proporciona un conjunto de macros para manejar los casos más comunes. Por ejemplo, para incluir los permisos que faltan, como open
, la regla anterior podría reescribirse como:
allow appdomain app_data_file:file rw_file_perms;
Consulte los archivos global_macros
y te_macros
para obtener más ejemplos de macros útiles. Las macros deben usarse siempre que sea posible para ayudar a reducir la probabilidad de fallas debido a la denegación de permisos relacionados.
Una vez que se define un tipo, debe asociarse con el archivo o proceso que representa. Consulte Implementación de SELinux para obtener más detalles sobre cómo se realiza esta asociación. Para obtener más información sobre las reglas, consulte el Cuaderno de SELinux .
Contexto de seguridad y categorías
Al depurar políticas de SELinux o etiquetar archivos (a través file_contexts
o al ejecutar ls -Z
), es posible que encuentre un contexto de seguridad (también conocido como etiqueta ). Por ejemplo: u:r:untrusted_app:s0:c15,c256,c513,c768
. Un contexto de seguridad tiene el formato: user:role:type:sensitivity[:categories]
. Por lo general, puede ignorar los campos de user
, role
y sensitivity
de un contexto (consulte Especificidad ). El campo de type
se explica en la sección anterior. Las categories
son parte del soporte de seguridad multinivel (MLS) en SELinux. Desde Android S, las categorías se utilizan para:
- Aísle los datos de la aplicación del acceso de otra aplicación,
- Aísle los datos de la aplicación de un usuario físico a otro.
especificidad
Android no utiliza todas las funciones proporcionadas por SELinux. Al leer documentación externa, tenga en cuenta estos puntos:
- La mayoría de las políticas en AOSP se definen mediante el lenguaje de políticas del kernel. Hay algunas excepciones para usar el lenguaje intermedio común (CIL).
- No se utilizan usuarios de SELinux. El único usuario definido es
u
. Cuando es necesario, los usuarios físicos se representan utilizando el campo de categorías de un contexto de seguridad. - Los roles de SELinux y el Control de acceso basado en roles (RBAC) no se utilizan. Se definen y utilizan dos roles predeterminados:
r
para sujetos yobject_r
para objetos. - No se utilizan las sensibilidades de SELinux. La sensibilidad
s0
predeterminada siempre está configurada. - No se utilizan los booleanos de SELinux. Una vez que se crea la política para un dispositivo, no depende del estado del dispositivo. Esto simplifica la auditoría y la depuración de políticas.