Recette de yaourt

Recette du yaourt maison

Ingrédients

  • 1 litre de lait tiède
  • 1 yaourt

Préparation

On prend une cuillère de yaourt, on l’incorpore dans le lait tiède, et quelques heures plus tard on a un yaourt

Pour les prochaines fois, on peut utiliser notre yaourt maison pour refaire d’autres yaourt maison !

Mais voilà la question : d’où vient le tout premier yaourt ?

Quelqu’un, quelque part, a dû en fabriquer un sans en avoir un. Et si ce yaourt originel était contaminé ? Mais pas assez pour être détectable au goûtn mais juste assez pour transmettre une contamination à chaque génération suivante, l’on serait empoisonné depuis le début sans jamais le savoir.

C’est exactement le problème que Ken Thompson a posé en 1984 dans son discours du Prix Turing. Sauf que lui il mentionnait les compilateurs.

Le compilateur qui se mord la queue

Un compilateur C, c’est un programme qui transforme du code source (lisible par un humain) en binaire exécutable par une machine. GCC, Clang, ce sont des compilateurs.

GCC est écrit en C. Donc pour compiler GCC (sortir un exécutable), il faut… GCC.

En pratique, aujourd’hui, l’on utilise une vieille version de GCC pour compiler la nouvelle. Mais ça déplace juste le problème. D’où vient la vieille version ? D’une encore plus vieille, et ainsi de suite jusqu’au tout premier compilateur C, compilé à la main en assembleur par quelqu’un, quelque part, dans les années 70.

Ce que Thompson souligne : si ce compilateur originel contenait une backdoor, on ne pourrait pas la trouver en lisant le code source.

L’attaque invisible

Imaginons un compilateur malveillant qui contient deux règles cachées :

  • Quand tu compile le programme login, injecte silencieusement une backddoor qui accepte un mot de passe secret.
  • Quand tu compiles un compilateur C, injecte ces deux mêmes règles dans le binaire résultant.

Maintenant, quelqu’un publie le code source de ce compilateur. Le code source est propre, les règles malveillantes n’y sont pas. Mais si tu utilises le binaire corrompu pour compiler ce code source propre, le nouveau binaire contiendra quand même les règles. Et le login compilé avec ce nouveau binaire aura toujours la backdoor.

Tu peux auditer le code source autant que tu veux. Tu ne trouveras rien, la corruption vit dans les binaires (la sortie), pas dans le texte (le code).

Le cas de xz

En 2024, un développeur a réussi à insérer une backdoor dans xz, un outil de compression présent sur quasiment tous les systèmes linux (je suis sur qu’il est installé sur votre machine) en gagnant la confiance de la communauté sur deux ans, en devenant mainteneur, puis en y glissant la modification au bon moment.

La supply chain logicielle, cette longue chaîne de dépendances entre compilateurs bibliothèques, outils de buils, est devenue l’un des vecteurs d’attaque les plus sérieux qu’il soit.

Remonter jusqu’au premier yaourt

Le projet Bootstrappable Builds, auquel Guix contribue activement, cherche à résoudre ce problème par la racine.

L’idée : si tu peux reconstruire toute ta chaîne de compilation depuis un point de départ assez petit pour être audité à la main, tu réduis drastiquement la surface d’attaque décrite par Thompson.

Guix maintient ce qu’on appelle un bootstrap seed. Un binaire Scheme minuscule, de quelques dizaines de kilooctets, depuis lequel l’intégralité de la chaîne d’outils est reconstruite. Pas de grosse boîte noire à avaler sur confiance : un point de départ auditable, et tout le reste compilé de façon traçable depuis ce point.

En plus de ça, Guix vise des builds reproductibles bit-à-bit : deux machines indépendantes qui compilent le même paquet depuis le même source doivent produire exactement le même binaire. Si ce n’est pas le cas, quelque chose cloche. La commande guix challenge fait exactement ça elle interroge des serveurs indépendants et compare leurs binaires octet par octet.

Pour les plus curieux : Introduction à Guix

Ce n’est pas magnique, il faut bien faire confiance à quelque chose au bout du compte. Le CPU, le microcode, le bootstrap seed lui-même.