Sections du handbook▾
Fondations
Comprendre les menaces qui pèsent sur un hôte LinuxPourquoi on durcitLes principes de défense derrière chaque règleConfiguration effective : la vérité qu'aucun fichier ne contientLes normes que Pavois cartographieModèle d'identifiant de contrôle SOCLEPreuves & exportsComment la note A-E est calculéeCe qu'un PASS prouve : le verdict qualifiéModèle de confiance du bundle de preuveSOCLE, n'est-ce pas votre propre norme ? (gouvernance & la question de la circularité)Ce que Pavois couvre, et ce qu'il ne couvre pasDomaines
Durcir SSHDurcir PAMContrôle d'accès obligatoire (SELinux / AppArmor)Durcir le pare-feu localDurcir sudoPermissions et propriété des fichiersDurcir les montages et le système de fichiersDurcir les modules noyauDurcir le noyau et le réseau avec sysctlJournalisation d'audit avec auditdDurcir la journalisation avec journald et rsyslogDurcir les services systemdHygiène des paquetsDurcir le chargeur d'amorçage (GRUB)Synchroniser l'heureBannières de connexion et MOTDContrôler l'accès à cron et atDurcir le bureau GNOME (dconf)Outillage
Annuler un durcissement : les points de restaurationExploiter Pavois : privilèges, air-gap, durée, dérogationsLancer Pavois en CI (GitHub Actions)État des fonctionnalités : livré, partiel, roadmapGouvernance : licence, versionnement, provenance, sécuritéDurcir les services systemd
Revu le
Chaque démon en cours d'exécution est une surface d'attaque accessible. Éteignez les unités inutiles et confinez celles que vous gardez, puis mesurez l'exposition de chacune.
La menace : démons oubliés et démons trop puissants
Une installation Linux standard démarre des dizaines d'unités que vous n'avez jamais demandées : une pile d'impression (cups), un résolveur de noms en cache, le Bluetooth, la découverte Avahi/mDNS, un shell de débogage, la collecte de core dumps. Chacune est du code qui s'exécute en processus privilégié, écoute souvent sur un socket, et peut être atteinte avant qu'un seul humain ne se connecte. La chaîne RCE cups-browsed de 2024 en est l'exemple type : un service dont presque personne n'avait besoin sur un serveur, à l'écoute du réseau, transformé en exécution de code à distance.
Un service oublié en marche est pire qu'un service choisi : il est hors de votre modèle de menace, non patché, non surveillé, et souvent activé par socket, donc il s'éveille à la demande même lorsqu'il paraît inactif. Et un démon qui doit tourner s'exécute avec bien plus de portée qu'il n'en a besoin (visibilité totale sur le système de fichiers, accès en écriture à /home, capacité à acquérir de nouveaux privilèges), si bien qu'une seule faille compromet l'hôte entier.
Pourquoi le durcir
Le service le plus sûr est celui qui ne tourne pas, et le deuxième le plus sûr est celui qui ne peut pas dépasser sa fonction. Désactiver les unités inutiles réduit la surface d'attaque : moins de ports ouverts, moins de processus privilégiés, moins de CVE qui vous concernent. Pour les démons gardés, le confinement plafonne le rayon d'impact : si le processus est compromis, le noyau lui refuse encore le système de fichiers, les répertoires personnels, les capacités supplémentaires et les appels système dangereux dont il ne se sert jamais légitimement.
Mesurer l'exposition d'abord : systemd-analyze security
Ne devinez pas quels services sont exposés, mesurez-les. systemd-analyze security liste chaque service avec un score d'exposition de 0.0 (sûr) à 10.0 (dangereux) et un verdict UNSAFE/EXPOSED/MEDIUM/OK ; systemd-analyze security <unité> détaille chaque directive de sandboxing et ce qu'elle apporterait. C'est la baseline avant et après durcissement, et le moyen le plus rapide de trouver le pire cas.
systemd-analyze security # classe tous les services par exposition
systemd-analyze security nginx.service # détail par directive + correctifs suggeresConfiner les services que vous gardez
Appliquez les directives dans un drop-in, jamais en éditant l'unité du paquet : systemctl edit <unité> écrit /etc/systemd/system/<unité>.d/override.conf, puis systemctl daemon-reload && systemctl restart <unité>. Les directives à forte valeur :
| Directive | Effet |
|---|---|
ProtectSystem=strict |
tout le système de fichiers en lecture seule sauf les chemins d'API (à coupler avec ReadWritePaths=) |
ProtectHome=yes |
/home, /root, /run/user rendus inaccessibles |
PrivateTmp=yes |
un /tmp privé, isolé de l'hôte |
PrivateDevices=yes |
un /dev minimal, pas de matériel brut |
NoNewPrivileges=yes |
bloque l'escalade setuid/setgid/capacités via execve |
ProtectKernelTunables/Modules/Logs=yes |
/proc+/sys en lecture seule, pas de chargement de module, pas de kmsg |
ProtectControlGroups=yes, ProtectClock=yes |
pas d'altération des cgroups ni de l'horloge |
RestrictAddressFamilies= |
seulement les familles de sockets nécessaires |
RestrictNamespaces=, RestrictSUIDSGID=yes, RestrictRealtime=yes |
refuse la création de namespaces, les fichiers setuid, l'ordonnancement temps réel |
MemoryDenyWriteExecute=yes, LockPersonality=yes |
pas de mémoire W+X, architecture figée |
SystemCallFilter=@system-service |
n'autorise que les appels système légitimes du service |
CapabilityBoundingSet= |
retire toute capacité Linux inutile au service |
Ce que Pavois audite : l'état systemd vivant
Le facteur différenciant : Pavois lit l'état systemd vivant, jamais un fichier de configuration. Pour chaque unité, il interroge le statut résolu is-enabled / is-active (la ressource service d'InSpec via systemctl), et voit donc ce que la machine fera vraiment au prochain démarrage, en tenant compte de l'activation par socket : un cups.service qui semble inactif peut être relancé par cups.socket, ce qu'un scan de /etc/cups/cupsd.conf ne décèlerait jamais.
Les règles de Pavois vérifient que les unités inutiles sont désactivées et arrêtées (cups, avahi-daemon, bluetooth, cockpit, nfs, rpcbind, snmpd, slapd, named, dnsmasq, autofs, smb, vsftpd, tftp, telnet, xinetd, rsyncd, dovecot, squid, apport, kdump, le debug-shell noyau et systemd-coredump) et que les unités liées à la sécurité sont activées et en cours d'exécution (auditd, systemd-journald, sssd, usbguard, fapolicyd, rngd, cron/crond). Les résultats sont mappés sur CIS, NIST CM-7 (fonctionnalité minimale) et ANSSI BP-028 R67, et le plan de durcissement peut désactiver/arrêter ou activer/démarrer chaque unité.
Pièges
ProtectSystem=strictsansReadWritePaths=rend en lecture seule les répertoires d'état/log/cache du service, qui ne démarre plus. Ajoutez les chemins où il doit écrire (/var/lib/<svc>,/var/log/<svc>).- Une directive trop agressive laisse le service actif mais muet : il démarre, puis ne peut silencieusement plus faire son travail (par ex. un appel système refusé). Surveillez
systemctl statuset le code de sortie. - Les codes de sortie du sandbox sont des indices :
226/NAMESPACE,227,228/SECCOMP,233/NETWORKpointent directement la directive trop stricte. maskcontredisable:systemctl disableempêche le démarrage automatique ;systemctl maskrend l'unité totalement indémarrable (garantie plus forte pour un service banni).
FAQ
Comment savoir quels services sont trop exposés ? systemd-analyze security les classe de 0 à 10 ; commencez par les UNSAFE.
Pourquoi Pavois lit-il systemctl et non la config ? Parce que l'activation par socket et l'état résolu enabled/active sont la vérité ; une unité peut être relancée par socket même quand son fichier de config paraît inerte.
Mon service ne démarre plus après le sandboxing. Pourquoi ? Le plus souvent ProtectSystem=strict sans ReadWritePaths=, ou un SystemCallFilter qui a retiré un appel nécessaire. Les codes de sortie 226-233 nomment le coupable ; relâchez la seule directive en cause, pas tout le sandbox.