LINUX:SELinux-Alertes et Journaux
But
Quand une règle est enfreinte, outre que l'accès demandé est refusé, une alerte est déclenchée et un message est envoyé aux journaux. Ce message arrive aux services "auditd.service" et "rsyslog.service". Lorsque cet événement arrive dans le fichier journal d'audit, le service "setroubleshootd.service" s’enclenche automatiquement. D'où l'importance d'activer ces deux services. Ce dernier service sera exploité par l'application Cockpit.
Journaux
Le service "auditd.service" écrit ses messages dans le fichier "/var/log/audit/audit.log" et le service "rsyslog.service" dans le fichier "/var/log/messages".
Voici un extrait de trois messages provenant du fichier "audit.log":
Jul 29 16:31:59 serverdb audit[16758]: AVC avc: denied { watch } for pid=16758 comm="fail2ban-server" path="/var/log/mariadb/mariadb.log" dev="dm-3" ino=1700802 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:mysqld_log_t:s0 tclass=file permissive=0 Dec 14 16:05:00 serverdb audit[3991714]: AVC avc: denied { write } for pid=3991714 comm="php-fpm" name="www-error.log" dev="dm-4" ino=785036 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_log_t:s0 tclass=file permissive=0 Aug 6 15:59:10 serverdb audit[731396]: AVC avc: denied { open } for pid=731396 comm="BackupPC_Admin" path="/sauvegarde/backuppc/pc/serverbck1.home.dom/LOCK" dev="dm-3" ino=268435555 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
On les repère par la chaine "AVC avc: denied".
Voici un extrait équivalent provenant du fichier "messages":
type=AVC msg=audit(1690544030.649:142): avc: denied { watch } for pid=1020 comm="fail2ban-server" path="/var/log/mariadb/mariadb.log" dev="dm-4" ino=1701672 scontext=system_u:system_r:fail2ban_t:s0 tcontext=system_u:object_r:mysqld_log_t:s0 tclass=file permissive=0 type=AVC msg=audit(1702566300.939:82055): avc: denied { write } for pid=3991714 comm="php-fpm" name="www-error.log" dev="dm-4" ino=785036 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:httpd_log_t:s0 tclass=file permissive=0 type=AVC msg=audit(1691485897.697:31328): avc: denied { open } for pid=1339363 comm="BackupPC_Admin" path="/sauvegarde/backuppc/pc/serverbck1.home.dom/LOCK" dev="dm-3" ino=268435555 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0
On les repère par la chaîne en début "type=AVC" et la chaîne "avc: denied" un peu plus loin.
Ce message comporte diverses informations sous forme de variables et de sa valeur séparés par le signe égal. En analysant leur contenu, on peut en déduire d'où provient le problème de blocage. Souvenons-nous que sous Unix, tout est représenté au travers de fichiers.
Voici une description de quelques unes de ces variables:
- pid : le n° du programme lancé
- comm : le nom du programme concerné
- path ou name : le chemin ou le nom du fichier concerné qui est utilisé par ce programme
- scontext : le contexte du fichier source effectuant l'appel au fichier cible
- tcontext : le contexte du fichier cible
- tclass : le type d'accès au fichier demandé
- {...} : la méthode d'accès au fichier demandé (en début de liste)
Par exemple pour la première ligne, le programme serveur Fail2Ban selon le type Selinux "fail2ban_t" essaye d'accéder au fichier "/var/log/mariadb/mariadb.log" ayant le type Selinux "mysqld_log_t"; il veut y accéder selon le type d'accès "file" grâce à la méthode "watch" qui est refusée (denied). Pour régler ce problème, il faudra ajouter par exemple une règle permettant cet accès ou corriger l'utilisation du programme.
Mais toute alerte peut être le symptôme d'une attaque.
Commandes de lignes
Il existe plusieurs commandes de lignes permettant de visionner ces alertes, telles "sealert" ou 'ausearch".
Nous n'allons pas les décrire car nous n'avons pas eu besoin de les utiliser directement. Nous les utiliserons indirectement au travers d'autres outils.
Cockpit
Nous avons ajouté un plugin pour SeLinux dans l'outil Cockpit (voir l'article sur Cockpit). Quand on y rentre, on aperçoit une nouvelle entrée SELinux dans le menu. La partie supérieure reprend les modifications apportées au paramétrage de SELinux et la partie inférieure les nouvelles alertes interceptées par le service "setroubleshootd.service".
Chaque alerte comprend deux onglets: un pour le descriptif de l'alerte et des conseils pour le résoudre et le second qui affiche le message repris dans le journal d'audit.
Remarque: Ne prenez pas les conseils de résolution des problèmes comme argent content. Nous présenterons par la suite une approche personnelle.
Configuration du service SeTroubleshootd
La configuration se trouve dans Le fichier "/etc/setroubleshoot/setroubleshoot.conf".
Nous avons modifié une des options afin de recevoir les alertes par mail:
use_sendmail = True
En complément, il faut ajouter l'adresse Email de réception dans le fichier "/var/lib/setroubleshoot/email_alert_recipients":
adebast@home.dom filter_type=never
Il existe divers filtres; nous avons choisi celui qui nous renvoie tous les messages.
Voici les messages correspondants aux deux alertes reprises dans l'interface de Cockpit.
Remarques:
- N'activez cette option que lorsque vous aurez résolu la majorité de vos problèmes de mise en route sinon vous serez submergés par les messages. Ne le faites pas également si vous désactivez le mode "DontAudit" (commande: "semodule -DB").
- Il m'est arrivé une fois que ce service était en erreur. Il suffit de l'arrêter; il redémarrera de lui même lors de l'alerte suivante:
systemctl stop setroubleshootd.service
- On peut remarquer le fichier "/var/lib/setroubleshoot/setroubleshoot_database.xml" qui s'amende de lui-même. Il est possible d'en nettoyer le contenu ou de l'effacer; il se recréera de lui-même lors du démarrage suivant du service. Il contient les informations sur les alertes retenues. Si vous effectuez un nettoyage via l'interface de Cockpit, ce fichier se nettoie de lui-même.
Script
Autre alternative, on peut créer un script qui extrait les nouvelles alertes des journaux d'audit ("/var/log/audit/audit.log") et des messages ("/var/log/messages") et de les envoyer par messagerie.
Cette approche présente d'autres avantages:
- Elle peut être exécutée à la demande dans le cas où on provoque une alerte; cet extrait me sert à créer un module spécifique comme on le verra dans un article suivant.
- Il m'a permis de me rendre compte que le service "setroubleshootd.service" se filtrait de toute une série d'alertes qu'il provoquait lui-même. Ces alertes étaient liées à l'envoi de mails.
- Il est arrivé, suite à une mise à jour, que le service "auditd.service" ne pouvait démarrer suite à un blocage SELinux. Dans ce cas, le fichier "auditd.service" n'était plus alimenté et donc le service "setroubleshootd.service" ne se déclenchait pas. C'est en extrayant les alertes du fichier "/var/log/messages" grâce à ce script que j'ai pu créer un module correctif. J'ai un autre script qui m'avait averti que le service "auditd.service" n'était pas démarré.
Voici un script qui peut effectuer cette tâche que l'on nommera "avc.bat" et placé dans le répertoire "/cron/selinux":
#!/bin/bash # *************************************************************************** # A adapter selon votre configuration # Répertoire de travail CHEMIN="/cron/selinux" # *************************************************************************** cd $CHEMIN # Isolation des alertes de l'audit /usr/bin/mv -f avc.audit.log avc.audit.archi.log /usr/bin/grep "^type=AVC " /var/log/audit/audit.log > avc.audit.log /usr/bin/sort avc.messages.log > avc.messages.sort.log /usr/bin/sort avc.messages.archi.log > avc.messages.archi.sort.log /usr/bin/comm -23 avc.messages.sort.log avc.messages.archi.sort.log > avc.messages.23 /usr/bin/rm -f avc.messages.sort.log avc.messages.archi.sort.log # Isolation des alertes et des messages /usr/bin/mv -f avc.messages.log avc.messages.archi.log /usr/bin/grep " AVC avc: denied " /var/log/messages > avc.messages.log /usr/bin/comm -23 avc.messages.log avc.messages.archi.log > avc.messages.23 # Dénombrement des alertes et des messages NBSA=`/usr/bin/wc -l avc.audit.23 | /usr/bin/awk '{printf("%s",$1)}'` NBSM=`/usr/bin/wc -l avc.messages.23 | /usr/bin/awk '{printf("%s",$1)}'` # En cas d'alertes, on envoie un message if [ "$NBSA" != "0" ] then TEST=1 /usr/bin/cp -f avc.audit.23 alerte.txt else if [ "$NBSM" != "0" ] then TEST=1 /usr/bin/cp -f avc.messages.23 alerte.txt fi fi # En cas d'alertes, on envoie un message if [ "$TEST" = "1" ] then echo "Subject: SELINUX - Problèmes d'accès" > ${CHEMIN}/sysmail.log echo -n "Serveur - " >> ${CHEMIN}/sysmail.log /usr/bin/hostname >> ${CHEMIN}/sysmail.log echo " " >> ${CHEMIN}/sysmail.log date >> ${CHEMIN}/sysmail.log echo " " >> ${CHEMIN}/sysmail.log echo "Liste AVC:" >> ${CHEMIN}/sysmail.log /usr/bin/cat alerte.txt >> ${CHEMIN}/sysmail.log echo " " >> ${CHEMIN}/sysmail.log /sbin/sendmail root < ${CHEMIN}/sysmail.log /usr/bin/rm -f ${CHEMIN}/sysmail.log /usr/bin/rm -f ${CHEMIN}/alerte.txt fi
On fait appel à ce script dans le Cron de Linux. On ajoute les lignes suivantes dans le fichier "/etc/crontab":
# Sauvegarde mysql */5 * * * * root /cron/selinux/avc.bat > /cron/selinux/avc.log
Ici on y fait appel toutes les 5 minutes.