La prophétie de 1984 devient réalité : un outil strip corrompu infecte tout un système Linux

SécuritéLinuxOpen SourceAttaque de la chaîne d'approvisionnementPorte dérobée de compilateur

Sources:arXiv + Lobsters + web research

En 1984, Ken Thompson montait sur la tribune du prix Turing de l’ACM pour formuler une mise en garde qui allait troubler durablement l’ensemble de la communauté informatique : même lorsque le code source d’un logiciel est intégralement public et auditable par tous, il peut renfermer des portes dérobées qu’aucun audit de code ne saurait déceler. Un compilateur malveillant peut injecter du code pirate dans les programmes lors de leur compilation et, surtout, reproduire cette même logique malveillante dans le binaire du compilateur de la génération suivante lorsqu’il se recompile lui-même. Dès lors, le code source pirate peut être effacé sans laisser de traces dans les dépôts, tandis que la porte dérobée se perpétue indéfiniment de génération binaire en génération binaire.

Quarante-deux ans plus tard, cette troublante prophétie vient d’être intégralement transposée dans la pratique. Dans une publication soumise le 27 juillet sur arXiv (2607.24888), des chercheurs de Télécom Paris et de l’Institut royal de technologie de Suède (KTH) ont prouvé qu’une telle attaque ne requiert même plus de compilateur. En altérant uniquement l’utilitaire GNU strip — un simple outil de post-traitement binaire chargé de purger les symboles de débogage —, la porte dérobée s’est propagée de proche en proche au cours du processus d’amorçage (bootstrap) de la distribution Linux NixOS, jusqu’à contaminer la quasi-totalité des exécutables du système d’exploitation.

Ken Thompson, lauréat du prix Turing 1984 et co-créateur d'Unix (photographié en 2019). Source : Wikimedia Commons Image : Ken Thompson, lauréat du prix Turing 1984 et co-créateur d’Unix. Source : Wikimedia Commons

Pourquoi l’attaque de compilateur est restée « difficile » pendant 42 ans

L’attaque originelle conçue par Thompson reposait sur un prérequis contraignant : le compilateur corrompu devait impérativement « se reconnaître lui-même ». Au moment de compiler son propre code source, il devait réinjecter la charge utile autoreproductrice dans le binaire produit. Pour parvenir à ce résultat, l’attaquant devait élaborer des mécanismes de détection syntaxique capables d’identifier des motifs précis dans le code source du compilateur, sous la forme d’un quine particulièrement fragile.

Cette dépendance rendait l’attaque intrinsèquement précaire. Dès lors que le code source du compilateur évoluait, faisait l’objet de refactorisations ou changeait de version majeure, la reconnaissance des motifs cessait de fonctionner et la chaîne de contamination se rompait. C’est pourquoi le consensus de l’industrie voyait dans l’attaque « Trusting Trust » de Thompson une expérience de pensée remarquable, mais pratiquement condamnée à l’échec face aux cycles de vie réels des logiciels.

Les chercheurs ont totalement contourné cette contrainte. Leur vecteur d’attaque s’appelle GNU strip, un utilitaire issu de GNU binutils dont l’unique mission est de supprimer les symboles de débogage et les tables de symboles des fichiers binaires compilés. Il n’inspecte, ne parse ni ne produit la moindre ligne de code source.

L’attaque s’opère exclusivement au niveau des binaires ELF, sans jamais toucher au code source. Quelles que soient les évolutions ou refactorisations du code source, la porte dérobée demeure parfaitement intacte. Elle s’avère infiniment plus tenace et difficile à éradiquer que son équivalent sur compilateur.

Comment la porte dérobée se transmet de génération en génération

Le scénario d’attaque s’appuie sur le mécanisme d’amorçage (bootstrap) propre à NixOS. Lorsque cette distribution reconstruit l’intégralité du système à partir des sources, elle démarre à partir d’une « graine binaire » (binary seed) composée d’une vingtaine de programmes précompilés — la racine de confiance initiale. À partir de cette graine, le système réédifie par étapes successives l’ensemble de sa chaîne d’outils jusqu’à atteindre l’environnement de compilation standard (stdenv), moment où la graine binaire d’origine est exclue de la clôture des dépendances d’exécution.

La méthode des chercheurs a consisté à modifier l’unique binaire de strip présent dans la graine initiale. Lorsque ce binaire intervient au fil des étapes de compilation, il implante la charge utile d’autoréplication dans le binaire strip de la génération suivante (ce que l’article qualifie d’« arête de succession » ou successor edge). Même lorsque la graine initiale quitte définitivement la clôture des dépendances, la charge malveillante survit et prend place au cœur du système final.

Vue d'ensemble de la conception et de la mise en œuvre de l'attaque. Source : arXiv 2607.24888 Image : Vue d’ensemble de la conception et de la mise en œuvre de l’attaque. Source : arXiv 2607.24888

L’attaque a été mise à l’épreuve sur une révision réelle de nixpkgs. Les chercheurs sont parvenus à générer l’image ISO complète d’un installateur graphique sans la moindre erreur de compilation. La clôture de dépendances obtenue regroupait 1 199 paquets et 3 799 binaires ELF exécutables, pour une empreinte disque de 6,16 Go.

L’ampleur de la contamination donne le vertige : sur 3 791 exécutables en ligne de commande (CLI), 3 790 se sont vu apposer la signature de la porte dérobée. Le seul programme ayant échappé à l’infection est Firefox 147.0.3 — uniquement parce que ses drapeaux de compilation contenaient l’option --disable-strip, contournant ainsi purement et simplement la phase d’exécution de strip.

Le fait qu’un logiciel ayant désactivé strip soit l’unique rescapé illustre, avec une ironie mordante, l’omniprésence dévastatrice de cette attaque.

Indépendant du langage et validé par tous les tests

Les exécutables compromis couvrent la quasi-totalité des grands écosystèmes de programmation : C et C++ (bash, git, sudo, curl, python3.13), Python (pydoc, idle), Rust (rsvg-convert), Go (captree) et Lua (lua). L’attaque est parfaitement indifférente au langage d’origine car elle n’analyse jamais le texte source : elle modifie directement les binaires ELF finaux.

Plus inquiétant encore : les tests de bon fonctionnement ont tous été concluants. Les chercheurs ont démarré une session de bureau NixOS complète dans une machine virtuelle. Les briques logicielles fondamentales telles que gnome-shell, mutter et nautilus avaient toutes été traitées par le binaire strip altéré, sans qu’aucun test fonctionnel n’échoue. Le système contaminé semblait fonctionner à la perfection — et c’est précisément ce qui rend cette offensive redoutable.

La publication détaille également un « mode de dormance » : la porte dérobée peut rester inactive, sans déclencher de charge destructrice ni chercher à s’étendre davantage lors des opérations usuelles, se bornant à se propager silencieusement de génération en génération jusqu’à ce qu’une cible ou un signal préprogrammé apparaisse. Ce type d’implant latent échappe à toute détection conventionnelle, le système hôte adoptant un comportement parfaitement irréprochable sous les outils de contrôle.

Une mise en garde vieille de 42 ans, toujours ignorée aujourd’hui

L’intervention de Thompson en 1984 a suscité des décennies de recherches sur les compilateurs de confiance. L’une des approches les plus reconnues est la double compilation diversifiée (Diverse Double-Compiling ou DDC), théorisée par David A. Wheeler, qui confronte les résultats de compilation entre plusieurs compilateurs indépendants. Pourtant, dans la réalité des faits, les distributions Linux grand public n’ont jamais déployé ces mécanismes de validation par défaut.

Les échanges sur des plateformes comme Lobsters ont rappelé des éléments historiques saisissants : Thompson avait déjà conçu et déployé un prototype fonctionnel dès 1984 ; les travaux de réduction d’amorçage dans GNU Guix et Nix (avec stage0-posix et hex0) ont été expressément conçus pour parer à cette menace en reconstruisant l’ensemble de la chaîne logicielle depuis les sources à partir de quelques dizaines d’octets de code machine (full-source bootstrap) ; enfin, Russ Cox avait récupéré le code original de Thompson, l’avait adapté pour Unix V6 et avait mis en ligne une démonstration permettant d’expérimenter cette porte dérobée directement dans un navigateur.

Toutefois, face aux impératifs d’ingénierie logicielle, l’amorçage intégral depuis les sources — qui permettrait d’éliminer la confiance aveugle accordée aux graines binaires précompilées — impose un coût colossal en temps de calcul et en maintenance. Un prix que l’immense majorité des distributions contemporaines se refuse toujours à payer.

La porte dérobée invisible aux audits de code

La portée profonde de cette étude remet en cause une croyance profondément ancrée : l’idée selon laquelle « code source ouvert » équivaudrait à « sécurité garantie » est une illusion. L’audit approfondi du code source permet certes de débusquer les failles et les portes dérobées dans les dépôts, mais il reste impuissant face aux manipulations opérées à l’échelle binaire. Après tout, nul n’aurait songé à vérifier si un simple outil voué à supprimer des informations de débogage injectait discrètement quelques octets pirates dans les en-têtes d’un fichier ELF.

Ken Thompson avait démontré en 1984 qu’une fois la chaîne de confiance brisée, l’audit du code source ne permettait plus de la rétablir. Quarante-deux ans plus tard, des chercheurs viennent de réitérer cette démonstration à l’aide d’un outil infiniment plus modeste, discret et insoupçonnable : strip.

Tant que les mécanismes d’amorçage dépendront de graines binaires précompilées, cette brèche demeurera béante. Et le prix à payer pour une vérification absolue — l’amorçage intégral depuis le code source — demeure une exigence que le monde du logiciel n’est toujours pas prêt à assumer.

Liens de référence :

  • Article arXiv 2607.24888
  • Discussion sur Lobsters (p5w5j6)
  • Ken Thompson, Reflections on Trusting Trust (1984)