Gérer correctement (enfin mieux) SELinux
Trop souvent je vois passer des tutos qui comme pré requis demandent de désactiver SELinux qui est pourtant un composant essentiel de la sécurité des systèmes Linux.
J’ai moi même par le passé encouragé le passage de SELinux en mode permissif, mais cela implique de surveiller le log d’audit.
Aujourd’hui on va regarder comment laisser SELinux activé, et régler correctement les blocages auxquels on va se confronter.
[cyklodev_summary]
Changer le mode SELinux
Connaitre le mode actuel
On peut connaitre le mode actuel en tapant la commande suivante:
[zeph@server ~]$ getenforce
Enforcing
Cette commande peut être faite même sans être l’utilisateur root.
Live
On peut changer dynamiquement (comprendre sans reboot) le mode SELinux avec cette commande (en root)
[root@server ~]# getenforce
Enforcing
[root@server ~]# setenforce 0
[root@server ~]# getenforce
Permissive
[root@server ~]# setenforce 1
[root@server ~]# getenforce
Enforcing
Vous pouvez donc voir que le mode change de suite, mais gardez à l’esprit que cette configuration ne supportera pas un reboot.
Permanent
Pour rendre le changement de mode permanent, il faut éditer le fichier suivant:
[root@server ~]# vi /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
On voit donc, qu’il y a un mode supplémentaire, qui est disabled, et qui ne peut pas être configuré sans un reboot du serveur.
Exemple de règle enfreignant SELinux
Un certificat auto signé pour Nginx
Comme exemple je vais prendre un cas courant ou en va utiliser un certificat auto signé pour un virtual host (vhost) Nginx.
La liste des postulats est la suivante:
- Vous avez déjà généré un certificat et sa clé avec openssl
- Vous avez déja un vhost nginx configuré
- SELinux est en mode permissif
Le certificat et sa clé sont dans le path suivant:
/etc/nginx/cert/self-signed.pem # certificat
/etc/nginx/cert/self-signed.key # clé
Le vhost nginx contient la section suivante (mais non exhaustive) :
server {
listen 443 ssl http2;
server_name srv-dg-dock.dg.lan;
...
ssl_certificate /etc/nginx/cert/self-signed.pem ;
ssl_certificate_key /etc/nginx/cert/self-signed.key ;
...
}
En admettant qu’aucun probleme de vhost propre à la syntaxe nginx ne soit présent. Un restart du service se passera sans souci.
[root@server ~]# getenforce
Permissive
[root@server ~]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
[root@server ~]# setenforce 1
[root@server ~]# getenforce
Enforcing
[root@server ~]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
Comme vous pouvez voir, le fait de réactiver SElinux empêche le redémarrage de nginx.
Analyser le log d’erreur
Comme pour tout service le premier pas dans l’analyse se fait dans le fichier de log, ici nginx
[root@server ~]#tail -n 10 /var/log/nginx/error.log
2020/11/02 10:03:01 [emerg] 14179#0: BIO_new_file("/etc/nginx/cert/self-signed.pem") failed (SSL: error:0200100D:system library:fopen:Permission denied:fopen('/etc/nginx/cert/self-signed.pem','r') error:2006D002:BIO routines:BIO_new_file:system lib)
L’erreur montre simplement que les droits ne sont pas corrects malgré un chmod 644
[root@server ~]# ll "/etc/nginx/cert/self-signed.pem"
-rw-r--r--. 1 root root 6992 Oct 27 05:02 /etc/nginx/cert/self-signed.pem
On est dans un cas simple, puisque on sait qu’on joue avec SELinux.
Auditer une exception
Les exceptions SELinux sont consignés dans le log suivant
/var/log/audit/audit.log
[root@server ~]# tail -f /var/log/audit/audit.log
type=AVC msg=audit(1604329381.498:1411): avc: denied { read } for pid=14179 comm="nginx" name="self-signed.pem" dev="dm-0" ino=34547784 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
On retrouve le nom de notre certificat avec le denied qui est explicite. On va tout de suite extraire l’id de événement (1411) qui nous aidera en utilisant l’utilitaire d’audit dédié.
A la place de parser le log, on peut utiliser ausearch avec l’id de l’événement.
[root@serveur ~]# ausearch -a 1411 -m avc
----
time->Mon Nov 1 10:03:01 2020
type=AVC msg=audit(1604329381.498:1411): avc: denied { read } for pid=14179 comm="nginx" name="self-signed.pem" dev="dm-0" ino=34547784 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
On récupère la même information, mais on ne sait toujours pas ce qui bloque. Pour en savoir plus, on va utiliser audit2why qui est contenu dans le paquet policycoreutils-python-utils.
[root@serveur ~]# audit2why -a
...
type=AVC msg=audit(1604329381.498:1411): avc: denied { read } for pid=14179 comm="nginx" name="self-signed.pem" dev="dm-0" ino=34547784 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
Was caused by:
The boolean httpd_read_user_content was set incorrectly.
Description:
Allow httpd to read user content
Allow access by executing:
# setsebool -P httpd_read_user_content 1
On comprend maintenant que la règle httpd_read_user_content est enfreinte et on a de suite la solution.
Corriger cette exception
[root@serveur ~]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
[root@serveur ~]# setsebool -P httpd_read_user_content 1
[root@serveur ~]# service nginx restart
Redirecting to /bin/systemctl restart nginx.service
Et voila on a pu corriger la configuration de SELinux pour avoir notre certificat auto signé ET en laissant SELinux en mode restrictif.
Le sujet est SELinux, ou AppArmor, est vaste et cela mériterait encore plusieurs articles, mais maintenant que vous savez faire, laissez SELinux activé !