Consultez cette page pour vous familiariser avec les concepts SELinux.
Contrôle d'accès obligatoire
Security-Enhanced Linux (SELinux) est un système de contrôle d'accès obligatoire (MAC) pour le système d'exploitation Linux. En tant que système MAC, il diffère du système de contrôle d'accès discrétionnaire (DAC) familier de Linux. Dans un système DAC, il existe un concept de propriété, selon lequel le propriétaire d'une ressource particulière contrôle les autorisations d'accès qui y sont associées. Il s'agit généralement d'une autorisation à granularité large, sujette à une élévation involontaire des privilèges. Toutefois, un système MAC consulte une autorité centrale pour prendre une décision sur toutes les tentatives d'accès.
SELinux a été implémenté dans le cadre du framework Linux Security Module (LSM), qui reconnaît divers objets du noyau et les actions sensibles effectuées sur ceux-ci. Au moment où chacune de ces actions doit être effectuée, une fonction de crochet LSM est appelée pour déterminer si l'action doit être autorisée ou non en fonction des informations stockées dans un objet de sécurité opaque. SELinux fournit une implémentation pour ces hooks et la gestion de ces objets de sécurité, qui se combinent à sa propre règle, pour déterminer les décisions d'accès.
En plus d'autres mesures de sécurité Android, la règle de contrôle des accès d'Android limite considérablement les dommages potentiels causés par les machines et les comptes compromis. L'utilisation d'outils tels que les contrôles d'accès discrétionnaires et obligatoires d'Android vous permet de structurer votre logiciel pour qu'il ne s'exécute qu'au niveau de privilège minimal. Cela atténue les effets des attaques et réduit la probabilité que des processus errants écrasent ou même transmettent des données.
Dans Android 4.3 et versions ultérieures, SELinux fournit un contrôle d'accès obligatoire (MAC) qui englobe les environnements de contrôle d'accès discrétionnaire (DAC) traditionnels. Par exemple, un logiciel doit généralement s'exécuter en tant que compte utilisateur racine pour écrire sur des périphériques de blocs bruts. Dans un environnement Linux traditionnel basé sur le contrôle d'accès discrétionnaire, si l'utilisateur racine est compromis, il peut écrire sur chaque périphérique de bloc brut. Toutefois, SELinux peut être utilisé pour libeller ces appareils afin que le processus auquel le privilège racine est attribué ne puisse écrire que sur ceux spécifiés dans la règle associée. De cette manière, le processus ne peut pas écraser les données ni les paramètres système en dehors du périphérique de bloc brut spécifique.
Pour obtenir d'autres exemples de menaces et de méthodes pour les contrer avec SELinux, consultez Cas d'utilisation.
Niveaux d'application
SELinux peut être implémenté dans différents modes :
- Permissif : la règle de sécurité SELinux n'est pas appliquée, mais uniquement consignée.
- Application : la règle de sécurité est appliquée et consignée. Les échecs s'affichent sous la forme d'erreurs EPERM.
Ce choix est binaire et détermine si votre stratégie prend des mesures ou vous permet simplement de recueillir les échecs potentiels. Le mode permissif est particulièrement utile lors de l'implémentation.
Types, attributs et règles
Android s'appuie sur le composant Type Enforcement (TE) de SELinux pour son règlement. Cela signifie que tous les objets (tels que les fichiers, les processus ou les sockets) sont associés à un type. Par exemple, par défaut, une application est de type untrusted_app
. Pour un processus, son type est également appelé son domaine. Il est possible d'annoter un type avec un ou plusieurs attributs. Les attributs sont utiles pour faire référence à plusieurs types en même temps.
Les objets sont mappés sur des classes (par exemple, un fichier, un répertoire, un lien symbolique, un socket) et les différents types d'accès pour chaque classe sont représentés par des autorisations.
Par exemple, l'autorisation open
existe pour la classe file
. Alors que les types et les attributs sont régulièrement mis à jour dans la règle SELinux d'Android, les autorisations et les classes sont définies de manière statique et rarement mises à jour dans une nouvelle version de Linux.
Une règle de stratégie se présente sous la forme suivante :
allow source target:class permissions;
où :
- Source : type (ou attribut) du sujet de la règle. Qui demande l'accès ?
- Cible : type (ou attribut) de l'objet. À quoi l'accès est-il demandé ?
- Classe : type d'objet (par exemple, fichier ou socket) auquel l'utilisateur accède.
- Autorisations : opération (ou ensemble d'opérations) effectuée (lecture ou écriture, par exemple).
Voici un exemple de règle :
allow untrusted_app app_data_file:file { read write };
Cela signifie que les applications sont autorisées à lire et à écrire des fichiers portant le libellé app_data_file
. Il existe d'autres types d'applications. Par exemple, isolated_app
est utilisé pour les services d'application avec isolatedProcess=true
dans leur fichier manifeste. Au lieu de répéter la règle pour les deux types, Android utilise un attribut nommé appdomain
pour tous les types qui couvrent les applications :
# 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 };
Lorsqu'une règle est écrite et spécifie un nom d'attribut, ce nom est automatiquement développé pour inclure la liste des domaines ou des types associés à l'attribut. Voici quelques attributs notables :
domain
: attribut associé à tous les types de processus.file_type
: attribut associé à tous les types de fichiers.
Macros
Pour l'accès aux fichiers en particulier, il existe de nombreux types d'autorisations à prendre en compte. Par exemple, l'autorisation read
ne suffit pas pour ouvrir le fichier ni pour appeler stat
sur celui-ci. Pour simplifier la définition des règles, Android fournit un ensemble de macros permettant de gérer les cas les plus courants. Par exemple, pour inclure les autorisations manquantes telles que open
, la règle ci-dessus peut être réécrite comme suit :
allow appdomain app_data_file:file rw_file_perms;
Consultez les fichiers global_macros
et te_macros
pour obtenir d'autres exemples de macros utiles. Dans la mesure du possible, utilisez des macros pour réduire le risque d'échec en raison de refus d'autorisations associées.
Une fois qu'un type est défini, il doit être associé au fichier ou au processus qu'il représente. Pour en savoir plus sur la façon dont cette association est effectuée, consultez Implémenter SELinux. Pour en savoir plus sur les règles, consultez le notebook SELinux.
Contexte et catégories de sécurité
Lorsque vous déboguez des stratégies SELinux ou que vous étiquetez des fichiers (à l'aide de file_contexts
ou de ls -Z
), vous pouvez rencontrer un contexte de sécurité (également appelé étiquette). Par exemple :u:r:untrusted_app:s0:c15,c256,c513,c768
. Un contexte de sécurité se présente au format suivant : user:role:type:sensitivity[:categories]
. Vous pouvez généralement ignorer les champs user
, role
et sensitivity
d'un contexte (voir Spécificité). Le champ type
est expliqué dans la section précédente. categories
font partie de la compatibilité Multi-Level Security (MLS) dans SELinux. Dans Android 12 et versions ultérieures, les catégories sont utilisées pour :
- Isoler les données de l'application pour empêcher une autre application d'y accéder
- Isoler les données d'application d'un utilisateur physique à un autre.
Spécificité
Android n'utilise pas toutes les fonctionnalités fournies par SELinux. Lorsque vous lisez de la documentation externe, gardez à l'esprit les points suivants :
- La majorité des règles de l'AOSP sont définies à l'aide du langage de règles du noyau. Il existe quelques exceptions à l'utilisation du langage CIL (Common Intermediate Language).
- Les utilisateurs SELinux ne sont pas utilisés. Le seul utilisateur défini est
u
. Si nécessaire, les utilisateurs physiques sont représentés à l'aide du champ "Catégories" d'un contexte de sécurité. - Les rôles SELinux et le contrôle des accès basé sur les rôles (RBAC) ne sont pas utilisés. Deux rôles par défaut sont définis et utilisés :
r
pour les sujets etobject_r
pour les objets. - Les sensibilités SELinux ne sont pas utilisées. La sensibilité
s0
par défaut est toujours définie. - Les valeurs booléennes SELinux ne sont pas utilisées. Lorsque la règle est conçue pour un appareil, elle ne dépend pas de l'état de l'appareil. Cela simplifie l'audit et le débogage des règles.