Sections du handbook

Durcir les modules noyau

Revu le

Chaque module chargeable est du code en mode noyau prêt à s'exécuter. Désactivez les systèmes de fichiers et protocoles réseau inutilisés pour qu'une socket égarée ou une image disque forgée ne les fasse pas surgir.

La menace : du code noyau dormant qui se charge tout seul

Le noyau Linux embarque des centaines de pilotes sous forme de modules chargeables, et la plupart peuvent être activés à la demande, automatiquement, sans aucune action de l'administrateur. Ouvrez une socket pour un protocole exotique et modprobe charge le gestionnaire ; insérez une clé USB et le pilote de système de fichiers correspondant la monte. Chaque module est du code s'exécutant avec tous les privilèges noyau : un bug d'analyse dans un pilote que vous n'utilisez jamais reste une voie vers l'élévation de privilèges ou le plantage du noyau.

Les suspects habituels sont des systèmes de fichiers obsolètes ou de niche (cramfs, udf, squashfs, freevxfs, hfs, hfsplus, jffs2), chargés automatiquement au montage d'une image forgée, et des protocoles réseau rarement utilisés (dccp, sctp, rds, tipc) qui sont accessibles à distance et affichent un historique de failles graves (par ex. le use-after-free CVE-2017-6074 de dccp donnant un root local). Laissés actifs, ils constituent une surface d'attaque latente qu'aucune règle de pare-feu ne voit.

Pourquoi le durcir

Il s'agit de code dormant dont vous n'avez pas besoin et que vous ne surveillez pas. Vous ne remarquerez pas que sctp est chargeable jusqu'à ce qu'un exploit en ait besoin, et il se chargera alors silencieusement dès qu'un attaquant ouvrira la bonne socket. Désactiver un module supprime entièrement le chemin de code : il n'y a plus rien à déclencher. C'est la forme la plus propre de réduction de la surface d'attaque (fonctionnalité minimale du CIS, CM-7 du NIST, ANSSI BP-028 R10) : on ne corrige pas le bug, on supprime la porte.

Le piège : la liste noire ne suffit pas

Une ligne blacklist <mod> dans /etc/modprobe.d/ n'empêche que le chargement automatique par alias. Le module peut encore être chargé explicitement (modprobe <mod>) ou tiré comme dépendance. Pour le désactiver vraiment, redirigez-le vers un no-op pour que toute demande de chargement échoue :

# /etc/modprobe.d/00-hardening.conf
install dccp /bin/false
blacklist dccp

install <mod> /bin/false exécute /bin/false au lieu d'insérer le module, et la ligne blacklist couvre le chargement automatique par dépendance. Les deux sont nécessaires.

Ce que Pavois audite : l'état effectif des modules

Pavois audite l'état effectif des modules, pas un seul fichier .conf. Chaque règle utilise la ressource InSpec kernel_module('<nom>') pour vérifier que le module n'est pas chargé (lu depuis le noyau vivant) et est désactivé (lu depuis la politique modprobe résolue via modprobe --showconfig). Ce double contrôle détecte les défaillances réalistes qu'un scan de fichier rate : un module en liste noire dans un drop-in mais toujours résident dans le noyau, ou réactivé par un override ailleurs dans /etc/modprobe.d/. L'ensemble couvre les systèmes de fichiers (cramfs, udf, squashfs, freevxfs, hfs, hfsplus, jffs2, overlayfs), les protocoles réseau (dccp, sctp, rds, tipc, atm, can) et les piles matériel/pilotes (usb-storage, firewire-core, bluetooth, la pile sans fil, uvcvideo).

Comment vérifier et opérer ?

  • Est-il chargé maintenant ? lsmod | grep <mod>.
  • Une tentative de chargement sera-t-elle refusée ? modprobe -n -v <mod> fait un essai à blanc ; sur un module désactivé il affiche install /bin/false, preuve que la politique est effective.
  • Quelle est la politique résolue ? modprobe --showconfig | grep <mod> montre le résultat fusionné de tous les drop-ins /etc/modprobe.d/, ce que lit Pavois.
  • Persistance : modprobe.d couvre le chargement à la demande, mais un module nécessaire tôt au boot vit dans l'initramfs (reconstruisez avec update-initramfs -u / dracut -f), et module_blacklist=<mod> sur la ligne de commande noyau le bloque encore plus tôt.
  • Verrouiller tout chargement : sysctl kernel.modules_disabled=1 fige l'ensemble des modules, root inclus, jusqu'au prochain redémarrage. Couplez-le à l'application des modules signés et au LSM lockdown sur un hôte pleinement durci.

Pièges

  • Ne désactivez pas un module utilisé par la charge de travail (un pilote de stockage/réseau/fichiers dont le serveur a besoin). Inventoriez avec lsmod d'abord.
  • La blacklist seule laisse ouverte la voie du chargement explicite : ajoutez toujours install <mod> /bin/false.
  • Un module déjà résident survit au changement de config jusqu'à son déchargement ou un redémarrage ; Pavois marque ces remédiations reboot_required.
  • Les machines cloud et virtuelles ont besoin de certains modules (virtio, le stockage/réseau de l'hyperviseur) : mettez en liste noire selon le rôle, pas à l'aveugle.

FAQ

Pourquoi install /bin/false ET blacklist ? blacklist bloque le chargement automatique par alias ; install /bin/false bloque le modprobe explicite et les chargements par dépendance. Ensemble, ils rendent le module vraiment non chargeable.

Pourquoi Pavois vérifie-t-il à la fois loaded et disabled ? Parce qu'un module peut être en liste noire sur le disque mais toujours résident dans le noyau ; seuls le noyau vivant et la politique résolue disent la vérité.

Comment bloquer tout chargement de module ? kernel.modules_disabled=1 (sysctl) jusqu'au redémarrage, root inclus ; combinez avec les modules signés et lockdown.