Désactiver le chargement et le déchargement des modules du noyau
Positionne kernel.modules_disabled=1 afin que le noyau refuse de charger ou de décharger le moindre module jusqu'au prochain redémarrage, y compris pour root. Une fois posé, cet interrupteur ne peut plus être annulé sans redémarrer.
Vérifié sur l’état résolu en cours d’exécution (ex. sshd -T, sysctl, systemctl show), attrape les drop-ins et Include qu’une lecture de fichier raterait. Réserve : runtime ≠ persistance ; une valeur correcte maintenant peut ne pas survivre à un redémarrage.
Pavois vérifie la configuration effective, l’état résolu et réellement appliqué, pas un fichier. Les scanners basés fichier (OVAL/SCAP, Lynis) ratent les Include, drop-ins et défauts runtime ; ce check voit ce qui est réellement en vigueur.
Un mapping est une référence croisée vers l’endroit où chaque norme situe cette exigence, ancrée et recoupée, pas une affirmation d’équivalence. Un check réussi est une preuve vers ces références, comment le lire.
Pourquoi cette règle
Un module noyau malveillant s'exécute avec les privilèges les plus élevés de la machine : il peut masquer des processus, détourner des appels système et neutraliser les protections en place. Interdire le chargement de modules ferme cette porte. Attention : une fois l'option positionnée, elle ne peut être annulée que par un redémarrage. Assurez-vous que tous les modules nécessaires sont déjà chargés avant de l'activer.
Ce que vérifie Pavois
Pavois lit la valeur effective dans /proc/sys/kernel/modules_disabled (ressource InSpec kernel_parameter), c'est-à-dire l'interrupteur que le noyau consulte réellement à chaque chargement de module. Un second contrôle prouve la persistance : il cherche la valeur dans /etc/sysctl.conf, les répertoires sysctl.d et les unités systemd de /etc/systemd/system/*.service, car Pavois applique ce réglage via une unité tardive plutôt qu'un simple drop-in sysctl (voir la remédiation). Une valeur seulement en mémoire disparaîtrait au prochain démarrage ; un fichier de configuration seul ne prouverait rien sur le noyau en cours d'exécution.
describe kernel_parameter('kernel.modules_disabled') do
its('value') { should cmp 1 }
end
describe command("grep -hsE 'kernel.modules_disabled[[:space:]]*=[[:space:]]*1' /etc/sysctl.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /lib/sysctl.d/*.conf /etc/systemd/system/*.service 2>/dev/null") do
its('stdout') { should match(/\S/) }
endComment vérifier qu’elle est appliquée
Vérifiez l'interrupteur en vigueur, puis prouvez qu'il mord réellement :
sysctl kernel.modules_disabled
# kernel.modules_disabled = 1
modprobe dummy
# modprobe: ERROR: could not insert 'dummy': Operation not permitted
systemctl is-enabled pavois-modules-disabled.service
# enabled
La dernière commande est ce qui garantit que le verrou est réappliqué à chaque démarrage.
Inspecter et investiguer
Un chargement de module refusé renvoie EPERM (Operation not permitted) à l'appelant : cela apparaît donc dans les journaux du composant qui a tenté le chargement (journalctl -u <service>, dmesg), et non dans un journal dédié. Les tentatives elles-mêmes sont enregistrées par le jeu de règles d'audit Pavois (init_module, finit_module, delete_module, clé modules) dans /var/log/audit/audit.log : cherchez key="modules" directement dans le fichier brut plutôt que de vous fier à ausearch, connu pour renvoyer de faux « aucun résultat ».
Remédiation
Pavois n'écrit pas cette clé dans son drop-in sysctl.d. systemd-sysctl s'exécute pendant sysinit, avant que local-fs.target ne monte /boot/efi : verrouiller le chargement de modules aussi tôt empêche à jamais le module vfat de se charger, local-fs échoue, et l'hôte tombe en mode d'urgence (machine irrécupérable si root n'a pas de mot de passe, constaté sur une VM EFI). Pavois écrit à la place une unité oneshot pavois-modules-disabled.service, ordonnée After=local-fs.target network-online.target, dont l'ExecStart est sysctl -q -w kernel.modules_disabled=1, et l'active : tous les modules de démarrage sont chargés d'abord, puis le chargement est verrouillé. Le verrou est réappliqué à chaque démarrage, et la règle porte reboot_required.
La règle est classée dangereuse : harden apply ne l'applique jamais de lui-même. Elle exige un acquittement explicite (acknowledged: true sur la règle dans le plan, ou --i-understand-danger).
Pavois applique ceci avec son propre moteur harden, le plan ci-dessous, pas un script shell :
| key | kernel.modules_disabled |
|---|---|
| reboot_required | true |
| resource | sysctl |
| value | 1 |
pavois harden plan localoù la cible est local, un alias SSH user@hôte, ou un conteneur , Docs
Impact & précautions
C'est un interrupteur à sens unique, et c'est pour cela que Pavois ne l'applique jamais automatiquement. Dès qu'il est posé, plus aucun module ne peut être chargé jusqu'au redémarrage : tout pilote qui n'est pas déjà en mémoire devient hors d'atteinte. Concrètement :
- Le pare-feu peut rester en rade. Le jeu de règles nftables déployé par Pavois utilise
ct state, qui a besoin denf_conntrack. Si ce module n'est pas chargé au moment où le verrou se ferme, le jeu de règles ne se charge pas : l'hôte se retrouve sans aucun pare-feu, ou avec son accès SSH coupé. C'est ce compromis qui justifie la dérogation documentée par Pavois sur les hôtes où un pare-feu fonctionnel prime sur le verrou. - Le matériel et les systèmes de fichiers peuvent disparaître. Brancher à chaud un disque, un périphérique USB ou une carte réseau, ou monter un système de fichiers dont le module n'a jamais été chargé (
vfat,nfs,xfs, une cibledm-*), échoue purement et simplement. - Les moteurs de conteneurs et les VPN cassent dès qu'ils chargent un module à la demande (
overlay,br_netfilter,wireguard,tun).
Avant de l'acquitter : inventoriez lsmod, préchargez tous les modules dont vous aurez besoin (/etc/modules-load.d/), assurez-vous que le pare-feu est levé et ses modules résidents, gardez un accès console (pas seulement SSH), et prévoyez un redémarrage pour confirmer que l'hôte revient avec le verrou réappliqué.
Mapping des normes
| Norme | Référence | Type | Version | Confiance |
|---|---|---|---|---|
| ANSSI BP-028 | R10 | direct | 2.0 | haute |
Chaque référence est une référence croisée ancrée dans le benchmark amont et recoupée avec le SCAP Security Guide et ansible-lockdown, pas une affirmation d’équivalence. Direct = une exigence prescriptive au niveau de la ligne ; support = une famille de contrôle abstraite (NIST) vers laquelle le check apporte une preuve. Comment lire un mapping.