2 points par GN⁺ 2024-04-13 | 1 commentaires | Partager sur WhatsApp
  • La backdoor XZ Utils/liblzma a été révélée le 29 mars 2024 sur la liste de diffusion Openwall OSS-security, et l’objectif final de l’attaquant était très probablement d’implanter une capacité d’exécution de code à distance dans le serveur OpenSSH sshd des distributions basées sur systemd
  • La chaîne d’infection reposait sur une injection en plusieurs étapes utilisant des fichiers de test et l’infrastructure de build du dépôt XZ ; via build-to-host.m4, bad-3-corrupt_lzma2.xz et good-large_compressed.lzma, un fichier objet malveillant était lié à liblzma pendant la compilation
  • Les versions XZ 5.6.0 et 5.6.1 contenant la backdoor ont été distribuées dans des builds bêta et expérimentaux de certains grands fournisseurs, et CVE-2024-3094 a reçu un score de criticité de 10
  • La backdoor binaire se charge en détournant l’IFUNC de GLIBC et le chemin d’appel cpuid, puis tente de surveiller les connexions de la machine infectée en hookant des fonctions liées à OpenSSL/libcrypto
  • Le code malveillant vérifie si /usr/bin/sshd est en cours d’exécution ainsi qu’une variable d’environnement servant de kill switch, et complique l’analyse et la détection grâce à un traitement de chaînes basé sur un trie, à une résolution dynamique des symboles et à un patch runtime de rtdl-audit

Vue d’ensemble de l’incident et périmètre d’impact

  • La découverte de la backdoor XZ a été rendue publique le 29 mars 2024 via un message sur la liste de diffusion Openwall OSS-security
  • XZ est un utilitaire de compression intégré à plusieurs grandes distributions Linux
  • Le cœur du risque tient au fait que liblzma, qui contenait la backdoor, pouvait être liée au processus du serveur OpenSSH sshd sur certaines distributions basées sur systemd
    • Ubuntu, Debian et RedHat/Fedora Linux ont patché OpenSSH pour utiliser des fonctionnalités de systemd, ce qui le rend dépendant de cette bibliothèque
    • Arch Linux et Gentoo sont considérées comme non affectées
  • L’objectif final de l’attaquant était très probablement d’ajouter une fonctionnalité d’exécution de code à distance via sshd que personne d’autre ne pouvait utiliser
  • Contrairement à d’autres attaques de chaîne d’approvisionnement centrées sur un unique patch malveillant, un faux paquet ou un paquet de typosquatting, cet incident s’apparente davantage à une opération en plusieurs étapes qui a failli réussir à compromettre des serveurs SSH dans le monde entier

Comment la backdoor a été introduite

  • La backdoor liblzma a été injectée à deux niveaux, en exploitant à la fois le processus de build et des fichiers de test
    • Le code source de l’infrastructure de build qui génère le paquet final a été modifié par l’ajout de build-to-host.m4
    • Des scripts et composants binaires cachés dans des fichiers de cas de test étaient extraits pendant le build
  • Le flux d’infection tournait autour de trois fichiers
    • build-to-host.m4 : script de build qui extrait le script de l’étape suivante
    • bad-3-corrupt_lzma2.xz : fichier de test contenant un script shell caché
    • good-large_compressed.lzma : fichier de test contenant un objet binaire malveillant caché
  • Le composant binaire malveillant extrait pouvait être lié avec la bibliothèque légitime pendant la compilation, puis transmis aux dépôts Linux
  • Les principaux fournisseurs ont distribué ce composant malveillant dans des builds bêta et expérimentaux
  • La compromission de XZ Utils s’est vu attribuer CVE-2024-3094, avec le score de criticité maximal de 10

Principale chronologie

  • 19 janvier 2024 : le nouveau mainteneur principal jiaT75 migre le site web de XZ vers GitHub Pages
  • 15 février 2024 : build-to-host.m4 est ajouté à .gitignore
  • 23 février 2024 : deux « fichiers de test » contenant l’étape de script malveillante sont ajoutés
  • 24 février 2024 : XZ 5.6.0 est publié
  • 26 février 2024 : un commit perturbant la fonctionnalité de sécurité Landlock est intégré dans CMakeLists.txt
  • 4 mars 2024 : la backdoor provoque un problème lié à Valgrind
  • 9 mars 2024 : les deux fichiers de test sont mis à jour, la fonction CRC est modifiée, et le problème Valgrind est « corrigé »
  • 9 mars 2024 : XZ 5.6.1 est publié
  • 28 mars 2024 : le bug est découvert et Debian et RedHat sont prévenus
  • 28 mars 2024 : Debian rétablit XZ 5.6.1 à la version 5.4.5-0.2
  • 29 mars 2024 : un e-mail public est publié sur la liste de diffusion OSS-security
  • 29 mars 2024 : RedHat confirme que des versions de XZ contenant la backdoor ont été distribuées dans Fedora Rawhide et Fedora Linux 40 beta
  • 30 mars 2024 : Debian interrompt les builds et lance une procédure de rebuild
  • 2 avril 2024 : le développeur principal de XZ reconnaît l’incident de backdoor

Les 3 étapes de la chaîne d’infection

  • Étape 1 : build-to-host.m4 modifié

    • Les releases du dépôt GitHub officiel de XZ contenaient les fichiers de test malveillants, mais ceux-ci n’ayant aucune occasion de s’exécuter, ils étaient au départ inoffensifs
    • Le code malveillant qui amorçait l’infection semble avoir été inclus dans les releases fournies depuis xz[.]tukaani.org, contrôlé par jiaT75
    • La plupart des distributions utilisaient cette URL, et la release téléchargée contenait le fichier build-to-host.m4 avec le code malveillant
    • build-to-host.m4 s’exécute pendant le build : il corrige avec tr les données « corrompues » de bad-3-corrupt_lzma2.xz, puis les décompresse avec xz -d
    • Le résultat de la décompression contient un script shell qui sera ensuite exécuté par /bin/bash
  • Étape 2 : script shell injecté

    • Le script injecté par le fichier .m4 malveillant vérifie qu’il s’exécute sur une machine Linux et dans le processus de build attendu
    • L’exécution de l’étape suivante utilise good-large_compressed.lzma
    • Ce fichier est bien compressé avec XZ, mais les données décompressées contiennent des données parasites
    • Le script exécute un pipeline head via eval pour extraire les données
    • Chaque commande head ignore les 1024 octets suivants, ou extrait les 2048 ou 724 octets suivants
    • Au total, 33 492 octets sont extraits
    • tail conserve les 31 265 derniers octets du fichier et ignore le reste
    • Ensuite, tr applique une substitution de base pour lever l’obfuscation, puis une deuxième commande XZ décompresse les octets transformés comme un flux lzma brut avant d’envoyer le résultat au shell
  • Étape 3 : extraction de l’objet de la backdoor

    • Le script shell de la dernière étape vérifie plusieurs conditions pour s’assurer qu’il s’exécute dans l’environnement attendu
    • Il vérifie que le projet est configuré pour utiliser IFUNC
    • Il vérifie que la compilation se fait avec GCC
    • Il vérifie ensuite que certains fichiers dont le script aura besoin existent dans le projet
    • Cette étape extrait un fichier objet caché à un autre offset de good-large_compressed.lzma
    • La procédure d’extraction exécute plusieurs commandes en séquence et transmet la sortie de chacune comme entrée de la suivante
    • L’outil XZ extrait good-large_compressed.lzma
    • eval $i et plusieurs appels à head sont utilisés
    • Les données binaires sont déchiffrées avec un algorithme personnalisé similaire à RC4
    • Le fichier compressé déchiffré est de nouveau extrait avec XZ
    • Après suppression de quelques octets au début, le résultat est enregistré sous liblzma_la-crc64-fast.o
    • Enfin, le script modifie la fonction is_arch_extension_supported dans le fichier crc_x86_clmul.h de liblzma
    • Il remplace l’appel __get_cpuid par _get_cpuid, supprimant ainsi un underscore
    • Ce changement permet à l’objet de la backdoor d’être lié à la bibliothèque

Mode de chargement de la backdoor binaire

  • Le code XZ d’origine contient des fonctions spécialisées pour le calcul CRC, lzma_crc32 et lzma_crc64
  • Ces deux fonctions sont stockées dans la table des symboles ELF avec le type IFUNC de GLIBC
    • IFUNC permet au linker dynamique de choisir dynamiquement la fonction à utiliser lors du chargement d’une bibliothèque partagée
    • XZ utilise cette fonctionnalité pour vérifier la présence de fonctionnalités récentes du processeur, CLMUL, SSSE3 et SSE4.1, puis décider s’il faut employer une fonction CRC optimisée
  • La vérification des fonctionnalités du processeur nécessite l’instruction cpuid, et le wrapper __get_cpuid fourni par GLIBC est appelé
  • Lorsque le script malveillant remplace __get_cpuid par _get_cpuid, l’appel du code est relié au symbole _get_cpuid présent dans le fichier objet de la backdoor
  • Le code initial de la backdoor est appelé deux fois, car lzma_crc32 et lzma_crc64 utilisent la même fonction modifiée _get_cpuid
    • Un simple compteur vérifie si elle a déjà été exécutée
    • Lorsque l’IFUNC lzma_crc64 appelle _get_cpuid et que la valeur du compteur est 1, l’étape de redirection vers le point d’entrée final démarre

Comportement à l’exécution et cibles du hooking

  • La backdoor initialise des structures contenant les informations clés du processus en cours d’exécution
  • Elle trouve l’adresse de la Global Offset Table (GOT) à l’aide d’offsets codés en dur, puis y repère le pointeur cpuid
  • Elle remplace ensuite ce pointeur par la fonction malveillante principale, de sorte que celle-ci soit appelée comme si cpuid était appelé
  • L’objectif principal est de hooker certaines fonctions afin de pouvoir surveiller les connexions entrantes vers la machine infectée
  • Les fonctions ciblées sont liées à libcrypto
    • RSA_public_decrypt : utilisée pour déchiffrer un texte chiffré signé avec une clé privée
    • EVP_PKEY_set1_RSA : utilisée pour définir la clé RSA d’un contexte donné
      • Absente des versions récentes des serveurs SSH, mais utilisée dans des outils autonomes de génération de clés SSH
    • RSA_get0_key : utilisée pour récupérer une clé RSA
  • Le processus de hooking nécessite l’accès à plusieurs structures internes et la manipulation de structures propres au processus ; le code malveillant effectue aussi des vérifications destinées à échapper à l’analyse

Vérifications de l’environnement d’exécution et techniques d’évasion de l’analyse

  • Vérification de sshd et du kill switch

    • La backdoor commence par analyser le linker dynamique ld-linux, qui résout dynamiquement les adresses de symboles
    • Elle vérifie que l’environnement d’exécution actuel correspond à ses critères
    • Elle vérifie que le processus courant est /usr/bin/sshd
    • Elle vérifie la présence d’un kill switch
    • Le nom du processus courant est extrait de argv[0]
    • Elle analyse toutes les variables d’environnement du processus pour vérifier si l’une correspond à une valeur présente dans sa table de chaînes interne
    • Si une variable d’environnement correspond ou si le processus n’est pas sshd, le code malveillant interrompt son exécution
    • L’unique variable de la table interne, yolAbejyiejuvnup=Evjtgvsh5okmkAvj, agit dans ce contexte comme un kill switch
  • Traitement de chaînes basé sur un trie

    • L’une des caractéristiques de la backdoor est l’utilisation d’une unique structure de trie pour les opérations sur les chaînes
    • Au lieu de comparer directement des constantes comme des noms de fonctions, ou d’utiliser des hashes de chaînes, elle vérifie si le résultat d’une recherche dans le trie correspond à une valeur constante donnée
    • La valeur magique de l’en-tête ELF renvoie 0x300 dans le trie
    • Le nom de fonction system correspond à la valeur de retour 0x9F8
    • Le trie sert non seulement aux comparaisons, mais aussi à trouver des chaînes dans le binaire hôte
    • Par exemple, une fonction qui utilise un pointeur vers une chaîne comme ssh-2.0 recherche cette chaîne dans le binaire hôte afin de ne pas laisser de données suspectes dans le corps de la backdoor
    • L’implémentation utilise un bitmask de 16 octets
    • Chaque moitié correspond aux plages d’octets d’entrée 0x00-0x3F et 0x40-0x7F
    • Les nœuds feuilles du trie font 2 octets ; 3 bits servent de flags et le reste est réservé à la valeur ou à l’emplacement du nœud suivant

Résolution des symboles et hooking de rtdl-audit

  • Routines de résolution des symboles

    • La backdoor contient au moins 3 routines de résolution des symboles destinées à trouver des structures ELF Symbol
    • Toutes les fonctions de résolution de symboles prennent en entrée la clé à rechercher dans le trie
    • L’une de ces fonctions parcourt tous les symboles pour trouver celui qui possède la clé recherchée et, lorsqu’elle le trouve, renvoie la structure Elf64_Sym
    • Cette structure est ensuite utilisée pour remplir des structures internes de la backdoor et conserver les pointeurs de fonctions nécessaires
    • Ce procédé ressemble aux routines de hashing d’API que l’on observe couramment dans les menaces Windows
    • La backdoor recherche ensuite de nombreuses fonctions OpenSSL libcrypto qui serviront dans ses routines cryptographiques
    • Elle suit le nombre de fonctions trouvées et résolues, puis utilise cette valeur pour décider si l’exécution peut se poursuivre ou doit s’arrêter
  • Faux allocator exploitant lzma_alloc

    • Un autre résolveur de symboles détourne lzma_alloc, une fonction de liblzma elle-même
    • lzma_alloc est une fonction qui aide à allouer efficacement de la mémoire en utilisant l’allocator par défaut, malloc, ou un allocator personnalisé
    • Dans la backdoor XZ, un faux allocator fait que cette fonction se comporte comme un autre résolveur de symboles
    • Le paramètre normalement utilisé comme « taille d’allocation » sert en réalité de clé de symbole dans le trie
    • Cette astuce vise à rendre l’analyse de la backdoor plus difficile
    • La backdoor résout dynamiquement les symboles pendant son exécution, sans se limiter à une résolution de tous les symboles en une fois ni uniquement au moment où ils sont nécessaires
    • Les cibles de résolution vont de fonctions OpenSSL légitimes à des fonctions comme system, qui exécute des commandes sur la machine
  • Patch runtime de rtdl-audit

    • La backdoor utilise la fonctionnalité rtdl-audit du linker dynamique pour hooker des fonctions
    • En temps normal, rtdl-audit permet à un développeur de créer une bibliothèque partagée personnalisée afin de recevoir des notifications d’événements du linker, par exemple la résolution de symboles
    • La backdoor XZ ne crée pas de bibliothèque partagée distincte ; elle patche à l’exécution l’interface par défaut déjà enregistrée en mémoire pour détourner la routine de résolution des symboles
    • La structure malveillante audit_iface stockée dans la variable globale dl_audit de la zone mémoire du linker dynamique contient l’adresse du callback symbind64
    • Lorsque le linker dynamique appelle ce callback, toutes les informations de symboles passent sous le contrôle de la backdoor, qui renvoie une adresse malveillante pour les fonctions ciblées afin de réaliser le hooking
    • Les adresses de dl_audit et dl_naudit sont obtenues en désassemblant les fonctions dl_main et dl_audit_symbind_alt
    • La backdoor contient un désassembleur interne minimal destiné au décodage d’instructions, largement utilisé pour trouver certaines valeurs, comme les adresses *audit

Distributions confirmées contenant la backdoor et informations de détection

  • Distributions source contenant la backdoor

    • xz-5.6.0
      • MD5 : c518d573a716b2b2bc2413e6c9b5dbde
      • SHA1 : e7bbec6f99b6b06c46420d4b6e5b6daa86948d3b
      • SHA256 : 0f5c81f14171b74fcc9777d302304d964e63ffc2d7b634ef023a7249d9b5d875
    • xz-5.6.1
      • MD5 : 5aeddab53ee2cbd694f901a080f84bf1
      • SHA1 : 675fd58f48dba5eceaf8bfc259d0ea1aab7ad0a7
      • SHA256 : 2398f4a8e53345325f44bdd9f0cc7401bd9025d736c6d43b372f4dea77bf75b8
  • Principaux artefacts analysés

    • bad-3-corrupt_lzma2.xz : 86fc2c94f8fa3938e3261d0b9eb4836be289f8ae
    • build-to-host.m4 : b4dd2661a7c69e85f19216a6dbbb1664
    • good-large_compressed.lzma : 540c665dfcd4e5cfba5b72b4787fec4f
    • liblzma_la-crc64-fast.o : 212ffa0b24bb7d749532425a46764433
  • Bibliothèques connues contenant la backdoor

    • Debian Sid liblzma.so.5.6.0
      • MD5 : 4f0cf1d2a2d44b75079b3ea5ed28fe54
      • SHA1 : 72e8163734d586b6360b24167a3aff2a3c961efb
      • SHA256 : 319feb5a9cddd81955d915b5632b4a5f8f9080281fb46e2f6d69d53f693c23ae
    • Debian Sid liblzma.so.5.6.1
      • MD5 : 53d82bb511b71a5d4794cf2d8a2072c1
      • SHA1 : 8a75968834fc11ba774d7bbdc566d272ff45476c
      • SHA256 : 605861f833fc181c7cdcabd5577ddb8989bea332648a8f498b4eef89b8f85ad4
  • Noms de détection

    • Les produits Kaspersky détectent les objets malveillants liés à l’attaque sous les noms HEUR:Trojan.Script.XZ et Trojan.Shell.XZ
    • Kaspersky Endpoint Security for Linux détecte le code malveillant dans la mémoire du processus SSHD sous le nom MEM:Trojan.Linux.XZ, dans le cadre de la tâche Critical Areas Scan
    • La règle Yara fournie est la règle liblzma_get_cpuid_function, destinée à repérer la fonction malveillante get_cpuid liée à CVE-2024-3094

1 commentaires

 
GN⁺ 2024-04-13
Avis de Hacker News
  • J’ai l’impression que cette phrase minimise en fait ce qui s’est réellement passé.
    Ce qui est encore plus effrayant que les aspects techniques de la backdoor, c’est l’ampleur et le niveau d’ingénierie sociale. La backdoor était le produit final, et si elle a pu être introduite, c’est parce qu’à ce moment-là l’ensemble du projet xz était déjà, depuis longtemps, sous l’emprise d’acteurs malveillants, à savoir « Jia Tan » et son entourage. Ils ont mené une guerre psychologique contre le mainteneur pendant plus d’un an, sans que le mainteneur ni personne d’autre ne s’en aperçoive.
    On se croirait dans un roman d’espionnage, et si ce genre de chose est possible, on se demande ce qui peut bien être en train de se passer dans d’autres projets en ce moment.
    Le code de la backdoor lui-même reflète le même état d’esprit. Il ne se contente pas d’essayer d’avoir l’air inoffensif : à travers les messages de commit, les commentaires, les noms de variables, le choix des commandes, etc., il construit activement une narration sur ce qu’il est censé faire en apparence, alors qu’en réalité il fait tout autre chose. La structure est faite pour que la première personne qui examine le code doute d’abord de sa propre compréhension, puis soupçonne un bug, et ne commence à envisager une intention malveillante que bien plus tard.

    • C’est vraiment difficile à croire. Cela peut sonner comme une théorie du complot, mais je me demande s’il n’y a pas eu une opération psychologique dans le monde réel pour que l’auteur original n’ait plus de temps à y consacrer et finisse par céder la propriété à un acteur malveillant.
      J’espère que des agences de renseignement, quelles qu’elles soient, enquêtent plus en profondeur sur cette affaire.
    • J’espère qu’on en tirera les leçons. En réalité, il se passe beaucoup de choses. Parmi les organismes soutenus par des États dans le monde entier et les groupes du marché noir, beaucoup ont pour mission d’obtenir des backdoors, et ils sont largement financés. C’est leur travail.
      C’est frustrant de voir, dans chaque fil HN sur les backdoors, cette possibilité rejetée comme de la paranoïa ou un délire de chapeau en papier aluminium. On fait comme si cela n’arrivait pas, alors que cette fois-ci n’est qu’un cas concret qui a été attrapé, et qu’il en existe d’innombrables autres qui ne l’ont pas encore été.
      Dans ce cas, comme il s’agissait d’un projet open source, la découverte était relativement plus facile, et pourtant il a fallu de la chance. Maintenant, pensez aux produits propriétaires : y placer une backdoor revient à infiltrer ou faire pression sur une seule organisation. Ce genre de chose arrive souvent. Personne ne veut y croire, mais c’est courant. Quiconque a travaillé dans une entreprise d’infrastructure technologique a probablement quelques histoires à raconter. Il est difficile d’en parler à cause des NDA, ou pour des raisons encore plus graves, mais cela arrive vraiment.
    • Je suis entièrement d’accord sur le fait que cela pousse la personne qui examine le code à douter de sa propre compréhension. Le niveau de manipulation, de minutie, de patience et d’acharnement investi dans cette affaire est stupéfiant.
      Cela peut être le résultat de l’obsession de quelqu’un, ou le travail d’une société de sécurité privée ou d’un acteur étatique qui mène ce genre d’opérations sur plusieurs projets comme un travail de bureau de 9 h à 17 h.
  • Il est naturel que l’attention se soit jusqu’ici concentrée sur le fait que la backdoor fonctionne et sur la manière dont elle atteint ses objectifs.
    Mais j’aimerais aussi voir une analyse plus approfondie des erreurs et des parties surconçues. Dans l’interview de Bryan Cantril [1], Andrés dit que cela ressemble à un composant de backdoor prêt à l’emploi, pas forcément conçu en connaissant précisément la manière dont il allait être distribué, et qu’il contient beaucoup d’éléments stupides. Par exemple, la recherche dans la table des symboles qui l’a poussé à enquêter.
    De même, je me demande pourquoi ils ont découpé 48 octets avec RC4 [2].
    J’aimerais entendre ce qui aurait pu être mieux fait avec plus de temps ou une meilleure équipe, ou au contraire où ils se sont plantés encore plus lourdement.
    [1] https://youtu.be/jg5F9UupL6I?si=gvXsYFXgagkGOMd4
    [2] https://twitter.com/matthew_d_green/status/17744729080201014...

  • Si j’ai bien compris, une mesure de durcissement utile serait que chaque bibliothèque liée dynamiquement ait sa propre GOT, puis que la table soit marquée en lecture seule une fois le linking dynamique terminé. Autrement dit, empêcher de patcher des entrées ifunc de l’autre côté d’une frontière dynamique.
    Cela pourrait améliorer la sécurité de la chaîne d’approvisionnement pour du code qui est lié quelque part mais jamais exécuté.
    Plus loin, il serait peut-être préférable d’implémenter ifunc de manière déclarative, afin d’éviter de déclencher l’exécution de code arbitraire dans chaque bibliothèque liée. La compatibilité ascendante rendrait cette implémentation difficile aujourd’hui, mais à long terme cela semble pouvoir être introduit par paliers. Par exemple, si une bibliothèque est construite avec un bit de fonctionnalité « ifunc de linking déclaratif », le linker dynamique échouerait à l’exécution si toutes les bibliothèques liées ne disposent pas du même indicateur de fonctionnalité.

    • Sous un autre angle, le problème vient du système de build.
      Aujourd’hui, la plupart des builds de bibliothèques consistent à exécuter des scripts très complexes et obscurs qui nécessitent un environnement Turing-complet. Cela offre aux attaquants une surface d’attaque infinie, et si le processus de build est détourné, cela crée des opportunités.
      Passer à un processus de build déclaratif, où l’exécuteur n’est qu’une machine à états limitée, aiderait. Il serait aussi intéressant d’exiger que tous les blocs de source soient reproductibles.
    • Oui et non, mais surtout non. Ce genre d’approche empêcherait simplement d’utiliser ifunc de cette manière, mais le point important est que l’auteur de cette backdoor a pu injecter du code arbitraire dans une bibliothèque qui entre dans l’espace d’adressage d’un processus sensible.
      À partir de là, toutes les défenses tombent. S’il le veut, il peut remapper la GOT en écriture ; même si ce comportement peut être détecté comme « suspect » ou si le système d’exploitation peut empêcher la transition, le code injecté peut détourner le flot de contrôle de centaines d’autres manières. Lecture/écriture arbitraires, exécution de code, tout est possible. Il n’existe pas de mesure d’atténuation capable d’empêcher une compromission à ce stade. S’il le souhaite, il peut exfiltrer la clé privée et l’envoyer directement à l’attaquant, ou lancer un shell. Essayer de concevoir une protection à ce stade est une perte de temps.
    • Marquer la table en lecture seule après la fin du linking dynamique ne fonctionne malheureusement pas. Le linking dynamique est paresseux, il n’y a donc pas de moment où il est « terminé ».
      Le bon pointeur de fonction est chargé lors du premier appel et inséré dans la table à la place du stub, et ce moment peut être arbitrairement éloigné dans le futur. En pratique, dans de grands écosystèmes de bibliothèques comme les apps gtk, la plupart des fonctions liées ne sont jamais appelées du tout.
    • Si vous compilez pour l’architecture hôte, vous pouvez désactiver complètement ifunc sans perte. Sur Gentoo, il est courant de compiler avec -march=native, et désactiver ifunc est simple en définissant -multiarch dans les USE flags de glibc. Je n’ai constaté aucun effet négatif.
    • Existe-t-il un langage de programmation capable de sandboxer les imports de bibliothèques ?
  • Concernant les trois premières étapes, cet article n’ajoute pas grand-chose à ce qu’on sait depuis deux semaines. C’est plutôt une bonne synthèse avec un organigramme.
    En revanche, la partie qui analyse le binaire avec autant de détail semble nouvelle.
    Comment le code source qui y figure a-t-il été produit ? Ils ont passé le tout dans un désassembleur, compris ce que faisait le code, puis renommé tous les symboles avec des noms descriptifs ? Pour quelque chose réalisé en deux semaines, cela paraît être un résultat considérable.

    • L’auteur est GReAT.
      Global Research & Analysis Team, Kaspersky Lab
      https://securelist.com/author/great/
      Comme l’auteur semble être l’équipe d’analyse de malware de Kaspersky Lab, il y a de fortes chances qu’ils soient assez bons en rétro-ingénierie de binaires.
    • L’outil visible dans les captures d’écran blanches est IDA Pro, un décompilateur.
      https://hex-rays.com/ida-pro/
  • Ce que j’aimerais vraiment savoir, c’est ce qui a exactement provoqué le délai initial de SSH qui a déclenché l’enquête sur xz. Quelqu’un l’a-t-il déterminé ?

    • Une opération ECC supplémentaire est effectuée à chaque connexion, mais sur un CPU moderne, cela ne devrait pas prendre 500 ms.
      D’après ceux qui ont fait la rétro-ingénierie du code, le message de commande devait aussi être lié à la clé d’hôte SSH. Donc, si la clé d’hôte était une clé RSA, il est possible qu’une opération de déchiffrement RSA supplémentaire ait aussi été effectuée à chaque connexion.
      Cela suffirait probablement à expliquer le délai.
    • Cela a peut-être été fait volontairement.
      C’est un moyen simple de déterminer depuis l’extérieur si le serveur est infecté, sans même tenter d’abord une injection de code.
  • Les auteurs connaissent très en profondeur les structures internes de glibc. C’est le genre de choses qu’on ne peut savoir qu’en étant plongé jusqu’au cou dans le code source, et il y a aussi beaucoup de techniques nouvelles.
    Le parseur ELF personnalisé et le désassembleur sont tellement complexes qu’il est difficile d’imaginer que ce code n’ait pas été utilisé ailleurs auparavant, ou ne le sera plus à l’avenir.
    Je me demande si cette affaire fera l’objet d’une enquête sérieuse à la hauteur de ce qu’elle mérite, mais j’en doute.

  • Quelqu’un a-t-il finalement analysé le bug de la backdoor qui a provoqué l’erreur Valgrind et le ralentissement de SSH ayant révélé l’affaire ?

    • Il semble que c’était clairement une écriture mémoire incorrecte : https://www.mail-archive.com/valgrind-users@lists.sourceforg...
      Le « correctif » Valgrind consistait à désactiver ifunc, ce qui désactivait la backdoor et faisait disparaître l’erreur.
      Le ralentissement venait, à ma connaissance, de toutes les recherches de symboles et d’instructions effectuées par la backdoor.
  • Si l’on cherche le retournement de situation, vu les efforts déployés par l’attaquant dans les scripts et le code pour éviter la détection, tout ce projet pourrait être une diversion, ou un plan de secours pendant que plusieurs autres tentatives étaient menées en parallèle.
    Comment garder une longueur d’avance sur ce genre de choses ? Le fait que la communauté se concentre sur SSHD aura-t-il un impact sur d’autres parties du système dans son ensemble ? Sur d’autres aspects techniques ou sociaux ?
    Les chapeaux en papier aluminium, c’est amusant.

    • Je ne suis pas optimiste. Il y a très peu de gens qui auditent réellement le contenu des binaires flatpak de Flathub. Ont-ils vraiment été compilés depuis les sources ? C’est en gros l’auteur qui affirme que oui. Un mécanisme de livraison aussi sophistiqué que celui de cette backdoor pourrait même ne pas être nécessaire.
    • On peut tout écrire soi-même et disposer d’une équipe dédiée composée de développeurs vérifiés.
      Ou bien acheter du code propriétaire à une entreprise comme Microsoft, en espérant qu’elle ait les ressources et la volonté d’examiner le code plus rigoureusement.
      Et il reste toujours l’approche consistant à avoir une excellente équipe d’opérations de sécurité pour détecter les activités réseau suspectes et les tentatives d’élévation de privilèges.
    • Comme moyen de garder une longueur d’avance sur des backdoors similaires, je pense à encapsuler le trafic sshd dans un tunnel spiped. Spiped se compile depuis les sources, est lié statiquement, et sa dernière version stable date de 2021.
    • Mon idée « chapeau en papier aluminium », c’est de se méfier des contributeurs open source. Pas parce qu’ils viennent d’un certain pays, ni parce qu’on ne semble jamais les avoir rencontrés en vrai.
      Mais un contributeur qui n’a aucun historique ni aucune trace en dehors du projet sur lequel il travaille devrait désormais être considéré comme un signal d’alerte.
    • Pas besoin de chapeau en papier aluminium. Des backdoors sont implantées dans des projets FOSS depuis avant qu’ils ne deviennent célèbres ; la différence cette fois, c’est que c’est fait par un acteur soutenu par un État.
      D’anciens groupes comme GOBBLES, ADM, ac1db1tch3z, ~el8 faisaient aussi ce genre de choses, tout comme des « chercheurs en sécurité » privés comme isec.pl.
      Ce qui pose problème cette fois, c’est que des acteurs étatiques exploitent le capitalisme d’entreprise qui a créé une époque où des projets d’infrastructure tiennent grâce à du travail sous-payé. Les acteurs malveillants disposent en pratique de ressources illimitées pour atteindre leurs objectifs.
      C’est finalement ce qui a créé la demande et l’émergence d’organisations comme NSO et Zerodium.
      Avant cela, les exploits et les backdoors n’avaient presque aucune valeur, et les hackers espéraient plutôt être sponsorisés ou recrutés par des entreprises comme Qualys.
  • J’ai vu plusieurs analyses de piratages de vulnérabilités zero-day par Google, et elles étaient déjà incroyablement impressionnantes, mais ce hack-ci pourrait bien être l’un des plus marquants de tous les temps.

  • J’ai vu que le dépôt xz était de nouveau sur GitHub, et que Lasse et un nouveau contributeur étaient en train de faire le ménage. Ils ont supprimé la prise en charge d’ifunc et ont commité dans le dépôt le code de génération des fichiers de test, afin de pouvoir créer ces fichiers sans blob. Cela semble aller dans la bonne direction.