Debian 10 et Secure Boot : comment s’adapter au démarrage sécurisé ?

I. Présentation

Ça y est, Debian 10 (alias Buster) est maintenant sorti depuis le début de l’été apportant son lot de nouveautés. Du côté de l’installation, on aura l’occasion de voir cela au travers d’un autre tutoriel. Je vais plutôt vous parler du nouveau mode de démarrage initié depuis cette nouvelle version de la distribution Debian.

En effet, parmi les notes de la "Release", on peut lire que la distribution s’adapte désormais au mode de démarrage sécurisé (aussi appelé secure boot) inclus dans les BIOS de nouvelle génération, appelé UEFI (Unified Extensible Firmware Interface). Mais, peut-être serait-il de rappeler la fonction de tous ces éléments.

II. Le Secure Boot

Comme nous venons de le dire le démarrage sécurisé (ou secure boot) est inclus dans la nouvelle génération de BIOS appelé UEFI. Cela doit permettre de sécuriser la chaîne de démarrage de l’UEFI du début à la fin du chargement du système d’exploitation afin de s’assurer qu’aucun éléments indésirables (rootkits ou bootkits) ne viennent compromettre l’intégrité de l’ensemble de l’ordinateur.

RAPPEL : un rootkit a la particularité de démarrer avant n’importe quel programme de sécurité du système d’exploitation. Aussi, il s’agit ici d’empêcher toute activation de code nocif, avant le démarrage définitif du système de la machine.

Ce mode de fonctionnement est issu des laboratoires de la firme Microsoft et lors de la mise à jour de Windows 8 vers Windows 8.1, ce fonctionnement a été automatiquement activé sur l’ensemble des équipements dédiés et labellisés pour ce système d’exploitation, provoquant ainsi des réglages inadaptés de certains UEFI. Ceci a donc déclenché l’apparition de messages d’erreur sur certains systèmes, voire même empêché certains serveurs de démarrer.

Certaines distributions se sont alors employées à autoriser le mode de démarrage sécurisé. Cela a été le cas pour des distributions telles que Fedora, puis Red Hat, qui n’ont pas hésité à débourser de l’argent pour acheter le sésame magique : le fameux certificat Microsoft permettant alors de démarrer une machine équipée d’un BIOS UEFI, sur lequel le mode de démarrage sécurisé serait activé.

Mais, Debian faisait de la résistant. En effet, le credo de cette célèbre distribution consiste à affirmer haut et fort qu’aucun logiciel hors du circuit Open Source ne pouvait être exécuté sur le système. Or, l’adjonction d’un tel certificat (même pour sa propre sécurité), n’entrait pas jusque-là dans la politique maison de Debian.

Depuis, Microsoft est sorti de son silence en déclarant que la fonction secure boot n’était pas configurée correctement dans l’UEFI et que celle-ci n’était pas activée dans le système du BIOS, provoquant de fait le message qui apparaissait précédemment. Pour régler cet inconvénient, deux solutions :

  • activer le mode de démarrage sécurisé dans son intégralité.
  • désactiver le secure boot lorsqu’il est pré-activée et pose problème.

REMARQUE : toutefois, il faut noter que les cas de figure varient selon la version du système BIOS et la marque de la machine.

Revenons en maintenant au fonctionnement du secure boot. Cette fonctionnalité est apparue avec les EFI, permettant de contrôler l’exécution des fichiers binaires au format portable exécutable, de la même façon qu’un exécutable Windows (dont l’extension est .exe), en les autorisant ou non à s’exécuter. Ces programmes ont pour extension .efi. Mais, afin d’être démarrés et déclarés bootables, ces programmes doivent être placés sur une partition FAT (16 ou 32 bits), lors du démarrage de la machine.

REMARQUE : ces partitions peuvent être situées sur une clé USB ou directement sur une des partitions du disque dur de la machine.

Or, avec l’arrivée de Windows 8, puis de Windows 8.1, Microsoft a imposé aux constructeurs de mettre en place ce fameux démarrage sécurisé sur les UEFI et permettre le démarrage des bootloaders Windows uniquement, en les sécurisant. Ainsi, aucun autre programme .efi n’est bootable, puisque leur démarrage sécurisé est actif, impliquant de fait que les autres systèmes d’exploitation, hébergés sur ce type d’équipement, ne peuvent alors démarrer. C’est pourquoi les communautés GNU/Linux se sont mobilisées pour permettre malgré tout d’utiliser ce genre de matériel avec des systèmes Linux. Le fait que Debian s’y mette aussi n’est pas sans conséquence.

En effet, le fait d’utiliser ce mode sécurisé de démarrage implique certaines considérations. En effet, certaines fonctions seront systématiquement désactivées, car elles risquent de modifier le noyau linux, court-circuitant la sécurisation de l’espace système :

  • Chargement de modules non préalablement signés par une clé de confiance.
  • Utilisation de kexec pour démarrer une image noyau non signée.
  • Hibernation et retour d’hibernation.
  • Accès à la mémoire physique et aux ports de l’espace utilisateur.

La Linux Foundation a travaillé sur ce problème et a imaginé un moyen de laisser activée la fonction de démarrage sécurisé. Les fichiers issus de cette réflexion sont :

  • PreLoader.efi
  • HashTool.efi

Mais, ces fichiers s’adressent toutefois à des utilisateurs chevronnés sachant parfaitement utiliser ce genre d’exécutables. Une autre solution consiste à utiliser l’utilitaire shim. Il s’agit d’un package logiciel agissant comme un premier stage de bootloader sur des systèmes UEFI. Cette fonction est devenue la racine de confiance de l’ensemble des programmes UEFI. Elle embarque une autorité de certification de clés (notée CA), utilisée alors pour signer les programmes : le noyau linux, le bootloader GRUB ou encore le gestionnaire de firmware fwupdate.

En plus de l’autorité de certification de shim, les utilisateurs peuvent gérer une base de clés supplémentaire appelée la Machine Owner Key (et abrégée en MOK). Ainsi, les utilisateurs peuvent ajouter ou supprimer facilement des clés de programmes au sein de ce réceptacle. Un gestionnaire appelé mokutil permet d’administrer les éléments au sein de cette base de données.

Toutefois, les modifications de ces clés de la base MOK ne peuvent être réalisées que depuis la console, lors de la phase de démarrage. Cela réduit alors le risque d’introduire des maliciels ou d’effectuer des actions abusant de la confiance du système, en introduisant de nouvelles clés à l’insu de l’administrateur.

De plus, dans l’architecture UEFI, il existe quatre variables importantes s’installant au sein d’une ROM de la carte mère de façon persistante :

  • La Platform Key (notée PK) contenant au plus une entité. Lorsque cette clé est effacée, le système désactive le secure boot et l’utilisateur peut alors modifier ses clés, sans vérification de signature.
  • La Key Exchange Key (notée KEK) contenant une ou plusieurs clés publiques RSA. Ainsi, la mise à jour des variables db ou dbx nécessite d’être signée avec l’une des clés privées associées aux clés publiques, contenues dans cette variable KEK.
  • La Signature Database (notée db) contenant une base de données des signatures, des clés publiques ou voire des hash de programmes autorisés à s’exécuter.
  • La Forbidden Signature Database (noté dbx) agissant comme une liste noire (ou blacklist) de programmes voulant s’exécuter.

III. Génération des clés

La mise en adéquation du mode sécurisé de démarrage avec la nouvelle version Debian 10 nécessite en premier lieu la génération de nos propres clés PK, KEK et db. Commençons par se créer un répertoire de travail :

$ mkdir efikeys
$ cd efikeys

Ensuite, passons à la création des clés en utilisant OpenSSL pour générer des clés RSA de longueur 2048 bits ainsi qu’un certificat X.509 en SHA-256 avec une expiration dans 10 ans :

$ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=PK-Debian/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256
$ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=KEK-Debian/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256
$ openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Kernel-SignKey-Debian/" -keyout db.key -out db.crt -days 3650 -nodes -sha256

REMARQUE : le contenu ou descriptif du champ CN (Common Name) est laissé à la discrétion de l’administrateur et peut être remplacé par n’importe quel texte que l’on souhaite.

Au final, nous disposons maintenant de trois certificats :

  • PK.crt
  • KEK.crt
  • db.crt

Ainsi que de trois clés privées associées :

  • PK.key
  • KEK.key
  • db.key

IV. Préparation et installation des clés

Puisque désormais nous avons nos clés et certificats, on peut générer une liste de signatures, signées au format .auth. En effet, la majorité des architectures UEFI n’acceptent que ce format. Pour cela, on doit récupérer l’utilitaire Open Source efitools. Ce package peut se télécharger depuis la page https://packages.debian.org/buster/efitools.

Ensuite, on doit générer la liste de signatures en les signant avec notre clé PK créée précédemment :

$ cert-to-efi-sig-list -g "$(uuidgen)" PK.crt PK.esl
$ sign-efi-sig-list -k PK.key -c PK.crt PK.esl PK.auth

On peut alors pratiquer de la même façon pour la clé KEK ainsi que la clé db :

$ cert-to-efi-sig-list -g "$(uuidgen)" KEK.crt KEK.esl
$ sign-efi-sig-list -a -k PK.key -c PK.crt KEK KEK.esl KEK.auth
$ cert-to-efi-sig-list -g "$(uuidgen)" db.crt db.esl
$ sign-efi-sig-list -a -k KEK.key -c KEK.crt db db.esl db.auth

La mise en place de ces clés est un peu plus délicate. En effet, pour les intégrer à notre architecture UEFI on va les transférer sur une clé USB et démarrer le menu UEFI pour se rendre dans la section "Key Management", afin d’exécuter les opérations suivantes (précisément dans l’ordre décrit ci-dessous):

  • Effacer les clés existantes (via l’ordre Clear Secure Boot Keys)
  • Mettre en place la clé auth (via l’ordre Set DB from File)
  • Mettre en place la clé auth (via l’ordre Set KEK from File)
  • Mettre en place la clé auth (via l’ordre Set PK from File)

Pour ces trois dernières actions, une fenêtre s’affichera à l’écran, permettant ainsi de sélectionner les fichiers stockés sur notre clé USB. Une fois les clés intégrées, on peut quitter le système en sélectionnant l’option "Save & Exit".

REMARQUE : jusque-là nous avons délibérément laisse la clé dbx de côté. Ainsi, on pourra au choix, générer une liste vierge ou récupérer un ancien fichier dbx présents dans le Secure Boot de notre UEFI. Par contre, il faudra signer ce dernier, à nouveau, avec notre nouvelle clé KEK et le remettre en place avec sa nouvelle signature.

V. Signature du binaire de démarrage

Maintenant que les clés sont intégrées, on doit encore signer le binaire à exécuter. Pour cela, on va utiliser l’utilitaire sibsign, tiré du paquet sbsigntool afin d’en créer une version .efi signée:

$ sbsign --key KEK.key --cert KEK.crt --output BootSigned.efi Boot.efi

ATTENTION : le fait d’utiliser la clé KEK et son certificat n’est pas une généralité et dépend fortement des machines sur lesquelles on effectue ces opérations. Il se peut qu’il faille remplacer l’utilisation de la clé KEK et de son certificat par ceux de la clé db.

Lorsque cela est fait, il ne reste plus qu’à déposer le fichier en sortie sur notre clé USB, sous l’appellation Bootx64.efi. La chaîne de démarrage est maintenant complète. Bien évidemment, on aurait aussi bien pu utiliser PXE et le protocole TFTP pour manipuler ces clés, en lieu et place de la clé USB.

En résumé, voici le genre d’architecture que nous avons construit :

Ce principe s’applique également aux modules noyau non signés ou à tout autre programme que l’on souhaiterait voir démarrer avant le bootloader GRUB. Maintenant, après cette première approche, on va vite s’apercevoir qu’au niveau du système, nombre de modules, pas encore inclus dans le noyau ne pourront plus fonctionner. En effet, certains modules sont fournis via DKMS (Dynamic Kernel Modules Support) et compilés à l’installation du paquet. Or, lorsque Secure Boot est installé et configuré, les modules non signés par la clé Debian ne sont pas activés. Voyons donc, comment traiter ce cas de figure.

VI. Signature des modules DKMS

Nous allons alors créer un couple de clés privée/publique en RSA sur 2048 bits. La clé publique sera convertie au format DER et chargée en base MOK (Machine Owner Key).

REMARQUE : afin de ne pas mélanger les clés servant à UEFI et celles que l’on va maintenant utiliser, nous les stockerons dans le répertoire /etc/dkms/keys.

Nous devons créer cette arborescence et y créer notre paire de clé de la façon suivante :

# mkdir -p /etc/dkms/keys
# chmod -R 700 /etc/dkms/keys
# cd /etc/dkms/keys
# openssl req -new -x509 -newkey rsa:2048 -keyout MOK.key -out MOK.crt -nodes -days 3650-subj "/CN=Srv01/"

On changera évidemment le nom de la machine Srv01 par celui de son environnement. De plus, on notera ici que l’on travaille directement avec le compte root et non plus le compte d’un utilisateur délégué. La conversion au format DER s’obtient en exécutant la commande suivante :

# openssl x509 -in MOK.crt -out MOK.der -outform DER

Maintenant, il faut intégrer ces clés dans notre base MOK. Pour cela, on va utiliser l’utilitaire mokutil indiquant à shim de charger les clés au prochain redémarrage :

# mokutil --import /etc/dkms/keys/MOK.der

Soit dit en passant, on comprend pourquoi shim s’appelle ainsi, il s’agit d’une véritable cale (ou emplacement de stockage) de clés !

ATTENTION : l’utilitaire mokutil demande la saisie et la confirmation d’un mot de passe afin de protéger l’accès à cette clé, lors de son chargement dans la base MOK via shim. Il est conseillé d’utiliser un mot de passe se saisissant facilement via le clavier, sinon on risque ne pas pouvoir le ressaisir par la suite.

Dès lors, il ne reste plus qu’à rebooter la machine et lors de la phase de redémarrage, un nouvel écran shim apparaitra et permettra alors d’importer la clé publique précédemment générée dans notre base MOK. Désormais, on peut alors manuellement signer les modules DKMS et leur permettre d’être pris en compte par la base MOK.

Heureusement, sous Debian, les modules DKMS ne sont pas compressés et peuvent donc être signer directement, via un simple modprobe du module. Dans le cas contraire, il faudrait utiliser un outil de signature tel que sign-file, utilisable comme suit :

# /usr/lib/linux-kbuild-<KernelVers>/scripts/sign-file sha256 <Private> <Public> <Module>

 

VII. Conclusion

Voilà vous savez tout ou presque sur la fonctionnalité de Secure Boot UEFI. Maintenant, il reste à mettre en application. Il est vrai que l’ensemble de la procédure peut s’avérer longue et rébarbative. Mais, je ne doute pas que la communauté Linux mette rapidement en œuvre une solution intégrée et adaptée à ce nouveau mode de démarrage.

Pour aller plus loin dans la démarche, on peut notamment automatiser la signature des modules DKMS permettant ainsi de les rendre utilisable immédiatement (sur des distributions autres que Debian). Quoi qu’il en soit, on ne coupera pas au fait de devoir redémarrer le serveur plusieurs fois afin d’intégrer les différentes clés dans la base de gestion de l’utilitaire shim. En espérant que cela vous sera utile pour sécuriser vos distributions Debian (ainsi que les autres d'ailleurs).

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

Philippe PIERRE

A exercé de nombreuses années en tant qu'administrateur de base de données et comme administrateur Système Unix/Linux. Il a enseigné les réseaux au CNAM (Paris). Aujourd'hui, employé en tant qu'ingénieur infrastructure, au sein d'un laboratoire pharmaceutique et administrant un cluster de calculs HPC, il connaît parfaitement les environnements GNU/Linux dans le cadre d'une entreprise et des systèmes de haute disponibilité. Il aime partager son expérience.

    philippe-pierre has 61 posts and counting.See all posts by philippe-pierre

    Laisser un commentaire

    Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

     

    Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.