Centos 7 et SELinux, quelques résolutions de problèmes

Lorsque l’on installe un serveur Centos 7 et que l’on active SELinux, on est par défaut dans la politique targeted. Cette politique, bien que déjà suffisante, ne répond pas à toutes les problématiques que l’on pourrait avoir sur un serveur. En effet, le fait de laisser des modules en unconfined peut clairement être un problème de sécurité.

Donc, la première chose à faire est d’installer une politique plus contraignante certes, mais surtout beaucoup plus restrictive.

Je préconise de passer directement en MLS avant d’installer les autres programmes. En effet, il est plus simple de résoudre les problèmes un par un, que de tous les avoir d’un seul coup.


# yum install selinux-policy-mls.noarch

Ce paquet ne vient pas tout seul

[root@ postfix]# yum deplist selinux-policy-mls.noarch
Modules complémentaires chargés : fastestmirror
Loading mirror speeds from cached hostfile
* base: centos.mirrors.ovh.net
* epel: ftp.nluug.nl
* extras: centos.mirrors.ovh.net
* updates: centos.mirrors.ovh.net
paquet : selinux-policy-mls.noarch 3.13.1-102.el7_3.15
dépendance  : /bin/bash
provider: bash.x86_64 4.2.46-21.el7_3
dépendance  : /bin/sh
provider: bash.x86_64 4.2.46-21.el7_3
dépendance  : coreutils
provider: coreutils.x86_64 8.22-18.el7
dépendance  : policycoreutils >= 2.5
provider: policycoreutils.x86_64 2.5-11.el7_3
dépendance  : policycoreutils-newrole >= 2.5
provider: policycoreutils-newrole.x86_64 2.5-11.el7_3
dépendance  : selinux-policy = 3.13.1-102.el7_3.15
provider: selinux-policy.noarch 3.13.1-102.el7_3.15
dépendance  : setransd
provider: mcstrans.x86_64 0.3.4-5.el7

Une fois cette politique installée, il faut aller modifier le fichier /etc/selinux/config et modifier la politique chargée pour mettre mls. Il est important de ne pas mettre la configuration en enforcing, sinon, le serveur risque de pas redémarrer.

Puis, il faudra installer policycoreutils-python-2.5-11.el7_3.x86_64 pour pouvoir manipuler les contextes de sécurité. Ce paquet nous sera nécessaire par la suite.

Il faut associer un compte utilisateur classique (celui qui administrera le serveur) à l’utilisateur SELinux staff_u. Ainsi, l’utilisateur devrait changer de rôle pour devenir sysadm_r pour pouvoir faire les actions d’administration.

Pourquoi le mettre dans staff_u et non en sysadm_u ? Simplement parce que SELinux va interdire la connexion en SSH des comptes associés à l’utilisateur SELinux sysadm_u. Ce paramètre est modifiable en manipulant les booléens SELinux, mais ce n’est pas conseillé.

Avant de redémarrer, il est nécessaire que SELinux relabellise le système de fichiers pour que les nouveaux contextes de sécurité soient appliqués. Pour cela, il suffit de taper


# touch /.autorelabel

Et de redémarrer le serveur. Le redémarrage va être plus long qu’un démarrage classique puisque le système va devoir parcourir entièrement le système de fichiers.

Premiers problèmes

Après la relabellisation et donc le redémarrage, certains fichiers ne possèdent pas le bon contexte de sécurité. Soit parce que le script de relabellisation n’a pas fonctionné correctement, soit parce que les fichiers ont été créés après le mécanisme. Dans tous les cas, vous aurez des erreurs et surtout, des restes de contextes de sécurité unconfined. Pour résoudre ce premier problème, il suffit de taper :


# restorecon -Rv /

Cette commande va forcer la relabellisation du système de fichiers.

Une fois cette première étape passée, vous allez sûrement installer des applications (serveur HTTP, MySQL, etc.). Cependant, vous allez être confrontés à ce genre de message et ce, malgré la relabellisation du système de fichiers.


type=AVC msg=audit(1488804756.793:6136): avc: denied { read } for pid=18603 comm="fail2ban-server" name="localtime" dev="sda1" ino=654211 scontext=system_u:system_r:fail2ban_t:s0-s15:c0.c1023 tcontext=system_u:object_r:locale_t:s15:c0.c1023 tclass=lnk_file

Pour résoudre ce problème, vous serez peut-être tenté de taper la commande magique (audit2allow) qui va lire le contenu des fichiers de logs SELinux et proposer une solution. Mais il se pourrait que l’erreur suivante apparaisse :


[root@ conf.d]# audit2allow -a
[Errno 2] Aucun fichier ou dossier de ce type: '/etc/selinux/mls/contexts/files/file_contexts.local'

Oupss… Bon, la résolution est assez simple puisqu’il suffit de créer le fichier file_contexs.local, même vide, pour que l’outil fonctionne correctement.

La solution au premier problème la plus naturelle est la suivante :


allow fail2ban_t locale_t:lnk_file { read };

Alors oui, il faut installer le paquet selinux-policy-devel (même si l’ANSSI dit que non, mais c’est nécessaire à la compilation et à la manipulation des politiques SELinux).


[root@ modules]# yum deplist selinux-policy-devel
Modules complémentaires chargés : fastestmirror
Determining fastest mirrors
* base: fr.mirror.babylon.network
* epel: fr.mirror.babylon.network
* extras: fr.mirror.babylon.network
* updates: fr.mirror.babylon.network
paquet : selinux-policy-devel.noarch 3.13.1-102.el7_3.15
dépendance  : /bin/sh
provider: bash.x86_64 4.2.46-21.el7_3
dépendance  : /usr/bin/make
provider: make.x86_64 1:3.82-23.el7
dépendance  : checkpolicy >= 2.5
provider: checkpolicy.x86_64 2.5-4.el7
dépendance  : m4
provider: m4.x86_64 1.4.16-10.el7
dépendance  : policycoreutils-devel >= 2.5
provider: policycoreutils-devel.x86_64 2.5-11.el7_3
provider: policycoreutils-devel.i686 2.5-11.el7_3
dépendance  : selinux-policy = 3.13.1-102.el7_3.15
provider: selinux-policy.noarch 3.13.1-102.el7_3.15

Mais cela ne suffira pas. En effet, vous allez avoir une violation d’une contrainte MLS puisque le lien symbolique est dans une sensibilité s15 et votre processus n’est qu’en s0-s15.

Il existe, au moins, deux solutions pour résoudre ce problème. La première, bien bourrine et qui peut laisser quelques failles de sécurité :


mls_file_read_all_levels(fail2ban_t);

Bon, la, on autorise le domaine fail2ban_t a contourné toute la politique MLS sur l’ensemble du système. Et surtout, vous allez avoir le même problème avec les autres applications qui ont besoin de lire la timezone (genre httpd ou maridb, toutes les applications dans la vraie vie). Donc, il va falloir autoriser l’ensemble des applications à contourner la politique MLS.

La seconde consiste à modifier le contexte de sécurité du lien symbolique et du fichier cible. Pour cela, on va taper les commandes suivantes :


chcon -hv system_u:object_r:locale_t:s0 /etc/localtime
chcon -hv system_u:object_r:locale_t:s0 /usr/share/zoneinfo/Europe/Paris

Avec cette méthode, il n’y a plus de violation des propriétés MLS.

Dernier point par rapport à ce premier post, il m’est arrivé de faire tout simplement crasher audit2allow sans trop savoir pourquoi. Ma supposition est que le fichier d’audit était bien trop gros (~8Mo) pour le programme, mais ce n’est qu’une supposition. La seule solution est de supprimer le fichier et de redémarrer le service d’audit.

Mail, Microsoft et trolls

Nous nous sommes retrouvés par malchance ou mégarde dans une blackliste mail. Ce qui avait pour conséquence que tous les mails envoyés vers les serveurs de Microsoft (hotmail et outlook en autre) nous étaient renvoyés avec le message suivant :


Host mx2.hotmail.com[65.55.33.135] said: 550 SC-001
(COL004-MC6F15) Unfortunately, messages from 5.135.176.69 weren't sent.
Please contact your Internet service provider since part of their network
is on our block list. You can also refer your provider to
http://mail.live.com/mail/troubleshooting.aspx#errors. (in reply to MAIL
FROM command)

Pour résoudre ce problème, nous avons dû remplir un formulaire en ligne pour se supprimer de cette blackliste. Pour ceux qui auront le même soucis, le lien est le suivant :

https://support.microsoft.com/en-us/getsupport?oaspworkflow=start_1.0.0.0&wfname=capsub&productkey=edfsmsbl3&locale=en-us&ccsid=636267274311800514

Chose amusante, le site de Microsoft n’accepte que des adresses IPv4, comme le montre la capture suivante MS Fail

Au moment de l’écriture de ce post, tout est rentré dans l’ordre. Il n’aura fallu que quelques heures pour être “dé-blacklisté”. Mais il faudrait quand même que Microsoft découvre que nous pouvons aussi l’IPv6.

SX, Centos 7 et un peu de sécurité

Comme vous l’avez sûrement vu, nous avons été offline pendant deux jours début mars. Cela nous a permis de passer de Centos 6 à Centos 7, Centos 6 arrivant à la fin de son support complet en Mai 2017 (comme l’indique le tableau suivant https://wiki.centos.org/About/Product ).

Je vais faire une série de petits posts sur les problèmes que nous avons rencontrés lors de l’installation, configuration et exploitation de cette nouvelle version de Centos 7 et des mécanismes de sécurité que nous avons voulus mettre en place.

Pourquoi choisir Centos ?

Il n’y a pas vraiment de vraies bonnes raisons. Les deux principales sont :

– Une distribution stable et fonctionnelle, c’est-à-dire que les paquets de base sont fonctionnelles et sont, pour la plupart, utilisables dès leur installation.
– Un support natif de SELinux. Si vous avez lu les précédents posts orientés Admin système et réseau, SELinux est le mécanisme de sécurité que nous avons choisi car il est intégré nativement au noyau et que les politiques de base sont presque toujours fonctionnelles. Nous aurions pu choisir “son grand concurrent”, à savoir Grsecurity, mais il est nécessaire de recompiler son noyau à chaque mise à jour, ce qui est assez contraignant.

Et, à la différence de ce que préconise l’ANSSI dans son guide de sécurisation d’un serveur Linux (https://www.ssi.gouv.fr/uploads/2015/10/NP_Linux_Configuration.pdf), nous avons choisi la politique MLS (multi-level security), qui, comme nous le verrons par la suite, ne s’est pas révélée sans conséquence.

La politique targeted, celle préconisée par l’ANSSI, laisse les utilisateurs et certaines applications n’ayant pas de politique SELinux spécifiques, dans un domaine non confiné (donc non contrôlé).

Inconvénient majeur : la version de certains paquets. En effet, PHP, Apache, etc, sont en version assez vieillottes, ce qui nous privent de fonctionnalités parfois importantes.

Qu’est-ce que l’on va installer ?

De manière non exhaustive :

– un serveur HTTP
– une base de données MySQL
– un serveur de mail
– un ensemble d’autres applications utiles à la gestion d’un serveur.

Et l’objectif étant de sécuriser le tout avec un peu de SELinx, un peu de Fail2Ban et un peu du reste.

SELinux et Fail2ban

Aujourd’hui, je vais vous présenter rapidement une configuration SELinux pour pouvoir utiliser Fail2ban de manière correcte.

Notre système système est toujours une Centos 6 à jour. La politique SELinux est une politique mls presque de base et l’objectif est de l’utiliser en mode enforcing.

# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: permissive
Policy version: 24
Policy from config file: mls

Fail2ban est un logiciel de protection réseau qui va bannir pendant un temps spécifique les IP qui “tentent des choses” sur notre serveur. Pour cela, il doit aller lire le contenu de certains fichiers. Suivant la configuration ces fichiers vont être : messages, daemon, syslog, etc.

Sur une configuration de base, le module de politique SELinux pour Fail2ban n’est pas assez bien renseigné et Fail2ban ne peut pas se lancer. Il est nécessaire de lui donner quelques accès supplémentaire pour qu’il puisse fonctionner correctement.

Sur notre configuration, Fail2ban ne s’occupe que de : ssh, bind, httpd et postfix. Pour pouvoir lancer correctement Fail2ban, il faut commencer par rajouter ces éléments. On notera que par défaut, Fail2ban n’a pas le droit d’aller lire le contenu des fichiers de log alors que c’est son but principal…

allow insmod_t fail2ban_t:fifo_file { write read };
allow insmod_t fail2ban_tmp_t:file { write };
allow insmod_t inotifyfs_t:dir read;
allow insmod_t var_log_t:file read

mls_file_read_all_levels(fail2ban_t);
allow initrc_t fail2ban_t:unix_stream_socket { connectto };
allow initrc_t fail2ban_var_run_t:sock_file { write setattr };
allow fail2ban_t var_log_t:file { read getattr };

Il est nécessaire de générer une exception au niveau MLS pour que Fail2ban puisse lire les fichiers qui ne sont pas à son niveau de sensibilité (No Read Up de Bell-La Padula). Les règles sur l’init permettent de pouvoir (re)lancer le programme depuis la commande run_init.

Si vous souhaitez en plus rajouter le fait que Fail2ban aille lire le contenu de /var/log/audit/audit.log (pour activer le ssh-selinux par exemple), il suffit de rajouter les lignes suivantes :

allow fail2ban_t auditd_log_t:dir search;
allow fail2ban_t auditd_log_t:file read;
allow fail2ban_t auditd_log_t:file open;
allow fail2ban_t auditd_log_t:file getattr;
allow fail2ban_t auditd_log_t:dir read;
allow fail2ban_t auditd_log_t:dir getattr;

Il ne reste plus qu’à compiler la politique, la charger et lancer Fail2ban avec la commande run_init.

Utiliser SELinux pour protéger un forum SMF

Un article un peu pratique : comment configurer SELinux pour protéger un forum de type SMF (simple machine forum) ? (c’est largement utilisable pour d’autres forums).

SELinux fera l’objet d’un billet spécifique donc je ne le présente pas ici.

La configuration de base

Pour être efficace, SELinux doit être en mode enforcing. De plus, comme on le verra dans un prochain billet, nous avons fait le choix d’utiliser la politique MLS.

La configuration du serveur

Nous utilisons la configuration suivante :

  • Centos 6 à jour
  • SELinux : politique MLS
  • LibSELinux-devel
  • HTTPD (apache)

En détails, les dépendances pour SELinux :

[root@ossus]# rpm -qa | grep selinux
libselinux-utils-2.0.94-7.el6.x86_64
libselinux-2.0.94-7.el6.x86_64
libselinux-devel-2.0.94-7.el6.x86_64
libselinux-python-2.0.94-7.el6.x86_64
selinux-policy-3.7.19-292.el6.noarch
selinux-policy-mls-3.7.19-292.el6.noarch
selinux-policy-targeted-3.7.19-292.el6.noarch

Avec la politique de base, nous avons donc

ps auxwZ | grep apache
system_u:system_r:httpd_t:s0-s15:c0.c1023 apache 4410 0.5 1.2 478756 49552 ? S 16:25 1:01 /usr/sbin/httpd

Le contexte d’apache est donc system_u:system_r:httpd_t:s0-s15:c0.c1023.

SMF est installé dans le répertoire /var/www/html/forum/.

La politique SELinux

Avec la politique de base de SELinux, les éléments présents dans /var/www/html ont le contexte suivant : httpd_sys_content_t

Par défaut, httpd_t n’a pas les permissions de modification (création, suppression, exécution, etc.). Pour preuve, les AVC générés par apache :

type=AVC msg=audit(1466969654.803:74508): avc: denied { add_name } for pid=29483 comm=”httpd” name=”” scontext=system_u:system_r:httpd_t:s0-s15:c0.c1023 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir
type=AVC msg=audit(1466969654.880:74511): avc: denied { setattr } for pid=29483 comm=”httpd” name=”” dev=sda1 ino=1182475 scontext=system_u:system_r:httpd_t:s0-s15:c0.c1023 tcontext=staff_u:object_r:httpd_sys_content_t:s0 tclass=file
type=AVC msg=audit(1466969656.954:74512): avc: denied { remove_name } for pid=29483 comm=”httpd” name=”” dev=sda1 ino=1702698 scontext=system_u:system_r:httpd_t:s0-s15:c0.c1023 tcontext=system_u:object_r:httpd_sys_content_t:s0 tclass=dir
type=AVC msg=audit(1467154855.120:80140): avc: denied { write } for pid=5473 comm=”httpd” name=”” dev=sda1 ino=1182554 scontext=system_u:system_r:httpd_t:s0-s15:c0.c1023 tcontext=staff_u:object_r:httpd_sys_content_t:s0 tclass=file

Donc par défaut, apache n’a pas la possibilité de modifier les répertoires présents dans le sous-répertoire du forum (ni les fichiers par extension).

Le problème c’est qu’il est nécessaire pour apache de pouvoir écrire dans certains répertoires comme celui du cache, des fichiers joints, avatar, etc.

Première méthode

On autorise tout : d’un point de vu sécurité, c’est pas top top. Il suffit de faire une règle

allow httpd_t httpd_sys_content_t:dir *;
allow httpd_t httpd_sys_content_t:dir *;

et on est tranquille.

Deuxième méthode

On fait ça proprement.

File context

Création du file_context spécifique :

var/www/html/forum/attachments system_u:object_r:http_wr_smf:s0
/var/www/html/forum/attachments/*.* system_u:object_r:http_wr_smf:s0

/var/www/html/forum/avatars system_u:object_r:http_wr_smf:s0
/var/www/html/forum/avatars/*.* system_u:object_r:http_wr_smf:s0

/var/www/html/forum/cache system_u:object_r:http_wr_smf:s0
/var/www/html/forum/cache/*.* system_u:object_r:http_wr_smf:s0

/var/www/html/forum/Packages system_u:object_r:http_wr_smf:s0
/var/www/html/forum/Packages/*.* system_u:object_r:http_wr_smf:s0

/var/www/html/forum/Settings.php system_u:object_r:http_wr_smf:s0
/var/www/html/forum/Settings_bak.php system_u:object_r:http_wr_smf:s0
/var/www/html/forum/Sources/Load.php system_u:object_r:http_wr_smf:s0

Quelques explications :

  • attachments : contient les pièces jointes mises sur le forum
  • avatars : explicite
  • cache : cache du forum
  • Packages : contient les archives pour installer des modules/mises à jour du forum
  • Settings.php : pour pouvoir modifier les configurations depuis le serveur
  • Load.php : coeur du forum

Tous ces fichiers ayant (presque) les mêmes demandent de permissions, on va leur créer un type spécifique http_wr_smf On pourrait affiner un peu en créant un contexte spécifique pour chaque catégories,, mais dans un soucis de clarté, on va rester simple.

Règle SELinux

Il reste maintenant à donner l’autorisation à apache de réaliser des actions spécifiques sur ce type.
On créé le nouveau type :

type http_wr_smf

Puis on fait les règles qui vont bien :

allow httpd_t http_wr_smf:file { read write create setattr getattr unlink open rename lock} ;
allow httpd_t http_wr_smf:dir *;

allow httpd_t http_wr_smf:filesystem { associate };
allow http_wr_smf fs_t:filesystem { associate };

On compile (j’ai volontairement omis les types requis à la compilation). On charge la nouvelle politique et on applique les nouveaux contextes de sécurité, soit en utilisant restorecon soit autorelabel.

On a donc un forum fonctionnel avec SELinux en enforcing.