Introduction aux concepts et à la gestion de SELinux
Objectif
Introduction aux concepts et à la gestion de SELinux
Système d’exploitation et versions logicielles
- Système d’exploitation : – Agnostique de la distribution Linux
Exigences
- Accès root sur une installation Linux fonctionnelle avec une politique SElinux valide
- Paquet PolicyCoreutils : Il fournit les utilitaires getsebool, setsebool, restorecon
- Paquet coreutils : fournit l’utilitaire CHCON
- policycoreutils-python package : fournit la commande semanage
- policycoreutils-newrole : fournit le programme newrole
- setools-console : fournit la commande seinfo
Difficulté
DOULEUR MOYENNE
Conventions
- # – nécessite que les commandes Linux données soient exécutées avec les privilèges root, soit directement en tant qu’utilisateur root, soit en utilisant la commande
sudo - $ – nécessite que des commandes Linux données soient exécutées en tant qu’utilisateur régulier non privilégié
Introduction
SELinux (Security Enhanced Linux) est une implémentation d’un système d’autorisation de contrôle d’accès obligatoire (MAC) dans le noyau Linux. Ce type de contrôle d’accès diffère des systèmes de contrôle d’accès discrétionnaire (DAC) tels que les listes de contrôle d’accès et les autorisations unix ugo/rwx standard, dans la façon dont l’accès à une ressource est fourni. Dans le cas de MAC n’est pas le propriétaire d’une ressource qui décide qui et comment peut y accéder : cet accès est basé sur les relations entre les domaines et les étiquettes, dictées par une politique et appliquées au niveau du noyau. Il est important de dire que les règles appliquées par SELinux et les autorisations système standard ne s’excluent pas mutuellement, et que les premières sont mises en œuvre après les secondes.
Statut SELinux possible
Il y a trois statuts possibles de SELinux : désactivé, permissif et appliqué. Dans le premier cas, SELinux est complètement éteint : il n’a aucun effet sur le système en cours d’exécution. En mode permissif, SELinux est actif : il consigne les violations de politique, mais il ne fait rien pour les bloquer. Enfin, lorsqu’il est en mode d’application, SELinux applique réellement sa politique.
Il existe de nombreuses façons de vérifier l’état de SELinux sur votre système. La première consiste à utiliser la commande appelée getenforce. Cette commande ne fait que signaler l’état de SELinux parmi les trois mentionnés ci-dessus. Pour avoir une sortie plus détaillée, vous pouvez utiliser l’utilitaire sestatus. Voici le résultat de la commande sur mon système (CentOS 7) :
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
Quelques informations utiles sont fournies : tout d’abord le point de montage SELinuxfs, dans ce cas /sys/fs/selinux. SELinuxfs est un pseudo système de fichiers, tout comme /proc : il est rempli au moment de l’exécution par le noyau Linux et contient des fichiers utiles pour documenter l’état de SELinux. Le répertoire racine de SELinux est, à la place, le chemin utilisé pour conserver les fichiers de configuration de SELinux, le principal étant /etc/selinux/config (un lien symbolique vers ce fichier est également présent dans /etc/sysconfig/selinux). Modifier directement ce fichier est le moyen le plus simple de changer l’état et le mode de selinux. Jetons un bref coup d’œil à son contenu :
cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
Le fichier est très bien commenté : en changeant les valeurs des variables SELINUX et SELINUXTYPE, on peut définir respectivement le statut SELinux et le mode SELinux. Les modes possibles sont : ciblé (par défaut), minimum et mls. Le mode ciblé est le mode par défaut : lorsque ce mode est actif, tous les processus ciblés sont protégés. Le mode minimum est un sous-ensemble du premier, dans lequel seuls des processus spécifiques sont protégés. Enfin, la politique mls c’est la plus sophistiquée, basée sur le concept de classification de sécurité : de non classifié à top secret : elle utilise le modèle Bell-La Padula, développé pour le ministère américain de la Défense.
Modification de l’état SELinux
Pour modifier l’état SELinux au moment de l’exécution, vous pouvez utiliser la commande setforce. Sa syntaxe est très simple : vous spécifiez le statut dans lequel vous souhaitez mettre SELinux, en choisissant entre Enforcing ou Permissive ou en fournissant une valeur booléenne référencée au statut d’application. Ce que vous ne pouvez pas faire avec cette commande, c’est désactiver complètement SELinux. Pour accomplir cela (non recommandé) et effectuer d’autres modifications persistantes, vous devez modifier le fichier de configuration principal, comme indiqué ci-dessus. Les modifications apportées à ce fichier sont appliquées après un redémarrage.
Comment fonctionne SELInux ?
Fondamentalement, SELinux travaille sur le concept d’entités : sujets, objets et actions. Un sujet est une application ou un processus (un serveur http par exemple), un objet est une ressource sur le système, comme un fichier, un socket ou un port. Enfin, une action est ce que ce sujet spécifique peut effectuer sur l’objet. Un sujet s’exécute sous un certain domaine, qui, par exemple, dans le cas du démon httpd est httpd_t. C’est facilement vérifiable en vérifiant un processus en cours d’exécution avec la commande ps : tout ce que nous avons à faire est d’ajouter le commutateur -Z (le commutateur -Z est souvent associé à SELinux sur les commandes qui le supportent, comme ls par exemple) :
ps -auxZ | grep httpd
La commande ci-dessus donne le résultat suivant (sortie tronquée) :
system_u:system_r:httpd_t:s0 apache 2340 0.0 0.2 221940 2956 ? S 14:20 0:00 /usr/sbin/httpd -DFOREGROUND
Fonctionnant sous le domaine httpd_t, le service httpd (subject) ne peut accéder qu’aux ressources (action) (objets) au sein des types SELinux associés. Une façon très simple de vérifier cela est de vérifier le répertoire /var/www. Le démon httpd doit pouvoir y accéder, vérifions donc de quel type ce répertoire est présent. Nous pouvons le faire en utilisant la commande ls avec l’interrupteur -Z :
ls -dZ /var/www
Les commandes nous donnent ce résultat :
system_u:object_r:httpd_sys_content_t:s0 /var/www
Le résultat nous montre le contexte SELinux complet et le répertoire /var/www étiqueté avec le type ttpd_sys_content_t. C’est tout à fait logique : la politique SELinux ciblée permet à un processus s’exécutant sous le domaine httpd_t d’accéder (en mode lecture seule) à tous les fichiers étiquetés avec le type httpd_sys_content_t, quelles que soient les permissions DAC définies sur le fichier. Si le processus tente une action non attendue par la politique, SELinux consignera l’erreur et, s’il est en mode d’application, bloquera l’action elle-même.
Utilisateurs SELinux
Nous avons vu ci-dessus comment une représentation d’un contexte SELinux complet semble être structurée :
system_u:object_r:httpd_sys_content_t:s0
Analysons cette structure en prenant en considération les trois premières parties (la quatrième est rattachée au mode MLS). La première section concerne les utilisateurs SELinux : chaque utilisateur SELinux a un ensemble différent de restrictions et est autorisé
à ne jouer qu’un ensemble spécifique de rôles SELinux qui donnent accès à des domaines SELinux spécifiques, qui, à leur tour, ne peuvent accéder qu’aux types SELinux associés.
Selinux users
can play
selinux roles
can go to
SELinux domains
have access to
SELinux
types
Pour avoir une idée claire des utilisateurs SELinux disponibles, nous pouvons exécuter :
semanage user -lCette commande nous donne une vue d’ensemble claire des relations utilisateurs – rôles :
SELinux User Prefix MCS Level MCS Range SELinux Roles
guest_u user s0 s0 guest_r
root user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r
sysadm_u user s0 s0-s0:c0.c1023 sysadm_r
system_u user s0 s0-s0:c0.c1023 system_r unconfined_r
unconfined_u user s0 s0-s0:c0.c1023 system_r unconfined_r
user_u user s0 s0 user_r
xguest_u user s0 s0 xguest_r
Voyons brièvement ce que certains des utilisateurs de SELinux décrits sont autorisés à faire :
- guest_u : ce type d’utilisateur n’a pas accès à la mise en réseau, n’a pas de privilèges d’exécution de script dans /home, et ne peut pas non plus utiliser les commandes sudo ou su pour obtenir des privilèges plus élevés. Il ne peut utiliser que le rôle guest_r
- staff_u : Les utilisateurs du système mappés à cet utilisateur SELinux ont accès à l’interface graphique, à la mise en réseau et à l’utilisation de la commande sudo pour obtenir des privilèges. Il peut basculer entre les rôles stuff_r, sysadm_r, system_r et unconfined_r rôles
- sysadmin_u : Identique à ci-dessus, plus peut également utiliser la commande su. Il ne peut jouer que le rôle sysadm_r
- system_u : Il s’agit de l’utilisateur affecté aux services système, aucun utilisateur du système ne doit y être mappé.
- unconfined_u : Ce type d’utilisateur n’a aucune restriction. Il est associé à la fois à unconfined_r et à system_r rôles
- xguest_u : Cet utilisateur de SELinux a accès à l’interface graphique et au réseau, mais uniquement via le navigateur Firefox. Il n’a pas de droits d’exécution pour les fichiers sous /home et n’a que le rôle xguest_r qui lui est associé
Comme vous pouvez le voir, les utilisateurs de SELinux sont identifiables, dans le contexte, ayant le suffixe _u. Il devrait être clair qu’ils sont une chose totalement différente des utilisateurs du système. Il existe une carte entre les deux, et il est possible de la voir en exécutant la commande semanage login -l :
semanage -l loginCe qui nous donne le résultat suivant :
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
La racine de l’utilisateur système est mappée à l’utilisateur SELinux unconfined_u, elle n’a donc aucune restriction. Aucun autre utilisateur n’est explicitement mappé, ils sont, par défaut, associés à l’utilisateur SELinux unconfined_u.
Changement d’utilisateur SELinux
À ce stade, vous pouvez vous demander comment il est possible de définir une carte entre un utilisateur du système et un utilisateur SELinux. Nous accomplissons cette tâche à l’aide de la commande semanage login. Dans l’exemple suivant, je modifie le mappage par défaut, en associant l’utilisateur factice de mon système à l’utilisateur SELinux guest_u :
semanage login -a -s guest_u dummy
L’option -a est l’abréviation de -add et est utilisée pour ajouter un enregistrement, tandis que l’option -s (abréviation de -seuser) spécifie l’utilisateur SELinux auquel l’utilisateur du système doit être mappé. Exécutons à nouveau semanage login -l pour voir si quelque chose a changé :
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s0:c0.c1023 *
dummy guest_u s0 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
Comme prévu, l’utilisateur factice du système est maintenant associé à l’utilisateur SELinux guest_u qui, comme dit précédemment, n’a pas accès au réseau. Vérifions-le de la manière la plus simple : nous essayons de ping google et voyons quel est le résultat :
[dummy@linuxconfig ~]$ ping google.com
ping: socket: Permission denied
Comme prévu, l’utilisateur factice n’est pas autorisé à utiliser le réseau, de sorte que la commande ping échoue. Pour supprimer le mappage, nous utilisons l’option -d (abréviation de –delete) :
semanage login -d -s guest_u dummy
N’ayant pas de mappage spécifique, l’utilisateur factice se rabattra sur l’utilisateur SELinux unconfined_u. Comme ce dernier n’a aucune restriction, si nous essayons à nouveau la commande ci-dessus, elle devrait maintenant réussir :
[dummy@linuxconfig ~]$ ping google.com
PING google.com (216.58.205.206) 56(84) bytes of data.
64 bytes from mil04s29-in-f14.1e100.net (216.58.205.206): icmp_seq=1 ttl=52 time=29.2 ms
[]
Gardez à l’esprit que les modifications apportées au mappage entre les utilisateurs et les utilisateurs SELinux ne seront effectives qu’après une nouvelle connexion.
Rôles SELinux
La deuxième partie dans un contexte SELinux concerne les rôles. Comme vous pouvez le voir sur la sortie de semanage user -l ci-dessus, chaque utilisateur SELinux peut jouer un ensemble spécifié de rôles SELinux : lorsqu’il y a plusieurs rôles pour un utilisateur SELinux, l’utilisateur peut également passer de l’un à l’autre à l’aide de la commande newrole, en utilisant la syntaxe suivante :
newrole -r newrole
Pour vérifier les domaines auxquels un rôle spécifique peut accéder, vous devez exécuter la commande seinfo. Ceci est fourni par le paquet setools-console. Par exemple, pour vérifier quels domaines sont accessibles à partir du rôle stuff_r, nous exécutons :
seinfo -rstuff_r -x
seinfo -rstaff_r -x (output truncated)
staff_r
Dominated Roles:
staff_r
Types:
abrt_helper_t
alsa_home_t
antivirus_home_t
httpd_user_content_t
httpd_user_htaccess_t
[...]
Domaines et types
La troisième partie d’un contexte SELinux concerne les domaines et les types, et est identifiable par la présence du suffixe _t dans la représentation du contexte. On l’appelle type s’il s’agit d’un objet, ou domaine s’il s’agit d’un processus. Jetons un coup d’œil.
J’ai créé un simple fichier .html à l’intérieur de l’Apache VirtualHost par défaut sur ma machine CentOS 7 : comme vous pouvez le voir, le fichier a hérité du contexte SELinux du répertoire dans lequel il a été créé :
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 test.html
Avec le httpd_sys_content_t, le fichier peut être lu par le processus httpd, comme confirmé en accédant à celui-ci dans le navigateur.
Essayons maintenant de changer le type de fichier et voyons l’effet de ce changement. Pour manipuler le contexte SELinux, nous utilisons la commande chcon :
chcon -t user_home_t /var/www/html/test.html
Nous avons changé le type SELinux du fichier en user_home_t : c’est le type utilisé par les fichiers situés dans les répertoires personnels users
par défaut. L’exécution de ls -Z sur le fichier nous donne la confirmation :
unconfined_u:object_r:user_home_t:s0 /var/www/html/test.html
Si nous essayons maintenant d’accéder au fichier à partir du navigateur, comme prévu.
La commande chcon peut être utilisée non seulement pour modifier le type de fichier, mais aussi l’utilisateur et la partie rôle du contexte selinux. Lorsqu’il est utilisé pour changer le contexte d’un répertoire, il peut également s’exécuter de manière récursive avec l’interrupteur -R, et peut attribuer un contexte également par référence : dans ce cas, nous ne spécifions pas les parties du contexte à modifier directement, mais nous fournissons la référence au fichier ou au répertoire auquel le contexte doit se conformer. Par exemple, faisons le fichier test.html ci-dessus, acquérons le contexte du répertoire /var/www/html :
chcon --reference /var/www/html /var/www/html/test.html && ls -Z /var/www/html/test.html
Nous pouvons voir à partir de la sortie des commandes ci-dessus, que maintenant le contexte du fichier a de nouveau changé, et c’est maintenant le même que celui du répertoire /var/www/html :
system_u:object_r:httpd_sys_content_t:s0 /var/www/html/test.html
Notez que les modifications apportées avec la commande chcon survivront à un redémarrage mais pas à un réétiquetage des fichiers : dans ce cas, les fichiers seront définis conformément à la politique d’origine de SELinux et les modifications seront perdues. Alors, comment pouvons-nous faire en sorte que le changement persiste ? Nous devons ajouter une nouvelle règle à la politique SELinux à l’aide de la commande semanage.
Supposons que nous voulions ajouter une règle dictant que tous les fichiers créés dans le répertoire /home/egdoc/test doivent avoir, par défaut, le type httpd_sys_content_t. Voici la commande que nous devons exécuter :
semanage fcontext -a -t httpd_sys_content_t /home/egdoc/test(/.*)?
Tout d’abord, nous invoquons la commande semanage spécifiant fcontext pour modifier les contextes de fichiers, puis nous ajoutons le commutateur -a pour ajouter un enregistrement et le -t, pour spécifier que nous voulons changer la partie type du contexte pour celle qui suit immédiatement.
Enfin, nous fournissons le chemin du répertoire avec une expression régulière qui signifie : /home/egdoc/test path suivi du caractère /, suivi de n’importe quel nombre de n’importe quel caractère, l’expression entière étant égale à 0 ou 1 fois. Cette expression régulière correspondra à tous les noms de fichiers.
Nous exécutons maintenant la commande restorecon avec l’option -R (récursive) sur le répertoire, pour appliquer la politique. Étant donné que la règle que nous avons ajoutée ci-dessus fait partie de la politique elle-même, tous les fichiers contenus dans le répertoire, ainsi que ceux nouvellement créés, auront le contexte que nous avons spécifié dans la règle.
Paramètres booléens SELinux
Les paramètres booléens Selinux peuvent modifier le comportement de SELinux et sont gérés à l’aide de valeurs booléennes. Nous pouvons interagir avec eux à l’aide de deux commandes : getsebool et setsebool, la première étant utilisée pour interroger l’état d’une option et la seconde pour la modifier.
Si nous passons l’option que nous voulons vérifier à getsebool, il nous donnera juste l’état de cette option, si nous le fournissons avec le commutateur -a, il nous montrera à la place tous les paramètres disponibles et leur état booléen respectif. Par exemple, si nous voulons vérifier l’état des options liées à httpd, nous pourrions exécuter :
getsebool -a | grep httpd
Voici un très court extrait de la sortie :
[egdoc@linuxconfig.org ~]$ getsebool -a | grep httpd
httpd_anon_write --> off
httpd_builtin_scripting --> on
[...]
Essayons maintenant de changer l’état de l’option httpd_anon_write et de l’activer. Comme mentionné ci-dessus, nous utilisons setsebool pour la tâche :
setsebool httpd_anon_write 1
Si nous vérifions maintenant la valeur de l’option, elle devrait avoir été activée :
[egdoc@linuxconfig.org ~]$ getsebool -a | grep httpd_anon_write
httpd_anon_write --> on
Tout s’est passé comme prévu. Cependant, les modifications apportées de cette manière ne survivront pas à un redémarrage. Pour accomplir cette tâche, nous devons utiliser la même commande, mais en ajoutant le commutateur -P : lors de son utilisation, les modifications seront écrites dans la politique et elles persisteront.
Il y a beaucoup de choses à prendre en compte lors de l’utilisation de SELinux, et l’affiner pour obtenir un comportement spécifique, tout en conservant les autorisations les moins possibles, peut prendre beaucoup de temps. Néanmoins, ce n’est pas une bonne idée, à mon avis, de l’éteindre complètement. Continuez à expérimenter jusqu’à ce que vous soyez satisfait des résultats et que vous atteigniez la configuration souhaitée :
vous gagnerez à la fois en sécurité et en connaissances.