Sections du handbook

Durcir le chargeur d'amorçage (GRUB)

Revu le

GRUB s'exécute avant le système et avant tout contrôle du système. Protégez-le par un mot de passe, verrouillez grub.cfg, et passez des options de durcissement sur la ligne de commande du noyau.

La menace : une invite de démarrage éditable, c'est un root non authentifié

Le chargeur d'amorçage s'exécute avant le système d'exploitation : avant les connexions, avant sudo, avant SELinux ou AppArmor, avant tout contrôle que vous avez configuré. Quiconque dispose d'un accès console ou physique peut interrompre GRUB, appuyer sur e pour éditer une entrée et réécrire la ligne de commande du noyau. Les manœuvres classiques consistent à ajouter single (ou 1) pour basculer en mode mono-utilisateur, ou init=/bin/bash pour remplacer init par un shell : les deux donnent une invite root non authentifiée qui contourne toutes les protections du système. De là, l'attaquant réinitialise le mot de passe root, lit ou réécrit les disques, ou installe de la persistance. Un grub.cfg lisible par tous divulgue l'agencement et les éventuels hachages qu'il contient, et un fichier inscriptible permet à un utilisateur local d'injecter des paramètres de démarrage qui survivent aux redémarrages.

Pourquoi le durcir

Le chargeur d'amorçage est la racine de la chaîne de confiance du démarrage : il décide quel noyau s'exécute et avec quels paramètres. S'il peut être édité sans authentification, aucun de vos durcissements en aval ne compte, l'attaquant démarre simplement en le contournant. Durcir GRUB ferme le chemin d'attaque physique/console et fait de la ligne de commande du noyau une couche de défense, en activant des mitigations qui ne peuvent être posées qu'au démarrage (correctifs de canaux auxiliaires CPU, hygiène mémoire, contrôle d'accès obligatoire).

Principes de défense appliqués

  • Authentification avant privilège : définir un superutilisateur GRUB avec un hachage password_pbkdf2 afin que l'édition des entrées ou l'accès au shell GRUB exige un mot de passe. C'est ce qui bloque l'édition single / init=/bin/bash.
  • La nuance --unrestricted : un mot de passe superutilisateur sans --unrestricted sur les entrées normales bloque chaque démarrage et fige une machine sans écran à l'invite GRUB. Ajoutez --unrestricted pour que le mot de passe ne protège que l'édition et le shell, pas le démarrage courant. C'est la façon la plus fréquente de bricker un serveur en le durcissant.
  • Moindre privilège sur les fichiers : grub.cfg doit appartenir à root:root et ne pas être lisible, inscriptible ni exécutable par groupe/autres (mode 0600), pour que son contenu ne fuite pas et qu'aucun utilisateur local n'altère les paramètres de démarrage (CIS 1.4.2, ANSSI BP-028 R29).
  • Défense en profondeur sur la ligne de commande du noyau : activer les mitigations au démarrage comme pti=on (Meltdown), les options spectre/MDS/L1TF, init_on_alloc=1/init_on_free=1 et page_poison=1 (mise à zéro mémoire contre les fuites use-after-free), slab_nomerge, vsyscall=none, et garder selinux=0 absent.

Ce que Pavois audite : effectif à l'exécution, pas le modèle

Un durcissement ne compte que s'il est effectif à l'exécution, pas seulement écrit dans /etc/default/grub :

  • Mot de passe GRUB (grub-password, sévérité haute) : Pavois recherche dans le grub.cfg généré, pour les agencements BIOS (/boot/grub, /boot/grub2) et EFI (/boot/efi/EFI/*/grub.cfg), ainsi que dans /etc/grub.d/, une directive set superusers et un password_pbkdf2/password. Il valide la configuration générée que GRUB charge réellement, pas un fragment de modèle.
  • Ligne de commande du noyau : chaque règle lit /proc/cmdline, la ligne avec laquelle le noyau en cours a réellement démarré, et y recherche l'option requise (pti=on, init_on_alloc=1, slab_nomerge, l'absence de selinux=0). Lire /proc/cmdline au lieu de /etc/default/grub détecte une option éditée mais jamais régénérée, ou régénérée mais pas encore prise en compte par un redémarrage.
  • Permissions de grub.cfg : root:root, aucune lecture/écriture/exécution par groupe/autres sur le vrai grub.cfg et sa variante EFI, gardé par un test d'existence only_if.

Quand pavois harden apply pose le mot de passe, il utilise la ressource grub_password (hachage PBKDF2, snippet dans grub.d, configuration régénérée, reboot_required) et ajoute automatiquement --unrestricted, de sorte qu'appliquer le contrôle ne vous verrouille jamais hors d'un démarrage normal.

Comment le poser et vérifier ?

  1. Générer un hachage PBKDF2 : grub-mkpasswd-pbkdf2 (RHEL : grub2-mkpasswd-pbkdf2) et copier la chaîne grub.pbkdf2.sha512....
  2. Déclarer le superutilisateur dans un snippet grub.d (par ex. /etc/grub.d/01_users) : set superusers="admin" puis password_pbkdf2 admin <hash>.
  3. Garder le démarrage normal sans intervention : ajoutez --unrestricted au CLASS dans /etc/grub.d/10_linux pour que les entrées démarrent sans mot de passe (seules l'édition et le shell sont protégés).
  4. Régénérer : update-grub (Debian/Ubuntu) ou grub2-mkconfig -o /boot/grub2/grub.cfg (RHEL), puis chmod 0600 sur le grub.cfg généré.
  5. Vérifier : cat /proc/cmdline pour les options en vigueur, grep -E 'superusers|password_pbkdf2|unrestricted' /boot/grub*/grub.cfg, puis redémarrer pour confirmer que la machine démarre seule et qu'appuyer sur e demande le mot de passe.

Pièges

  • Un mot de passe sans --unrestricted bricke un boot headless : la machine fige à l'invite mot de passe GRUB. Toujours les associer.
  • Éditer /etc/default/grub ne suffit pas : rien ne change tant que vous n'avez pas régénéré grub.cfg et redémarré. Pavois lit /proc/cmdline, donc il dit la vérité.
  • Les chemins EFI et BIOS diffèrent : le vrai grub.cfg peut être sous /boot/efi/EFI/<distro>/. Éditez et vérifiez celui réellement utilisé.
  • Récupération : si vous vous verrouillez dehors, démarrez le média d'installation en mode rescue pour corriger le snippet.

FAQ

Un mot de passe GRUB empêche-t-il la machine de démarrer seule ? Seulement si vous oubliez --unrestricted. Avec lui, les entrées normales démarrent sans intervention et le mot de passe n'est requis que pour éditer une entrée ou ouvrir le shell GRUB.

Pourquoi Pavois lit-il /proc/cmdline et le grub.cfg généré plutôt que /etc/default/grub ? Parce que /etc/default/grub est un modèle ; le noyau démarre avec /proc/cmdline et GRUB charge le grub.cfg généré. Une option éditée mais jamais régénérée, ou pas encore redémarrée, est un faux succès sur le modèle.

Où mettre le mot de passe ? Dans un snippet /etc/grub.d/ (pour que grub-mkconfig le rende dans grub.cfg), jamais en éditant directement le grub.cfg généré.