1 points par GN⁺ 2024-04-02 | 1 commentaires | Partager sur WhatsApp
  • xzbot est un dépôt pour explorer la backdoor xz (CVE-2024-3094), qui fournit aussi un honeypot, un patch de clé publique ED448, le format du payload de la backdoor et une démo d’exécution de code à distance
  • Le honeypot applique un patch simple à OpenSSH afin d’enregistrer dans les logs de sshd les tentatives de connexion utilisant une valeur N de clé publique correspondant au format de la backdoor
  • Le patch ED448 remplace la clé publique codée en dur utilisée par la backdoor pour vérifier la signature et déchiffrer le payload par une clé générée par l’utilisateur, afin de pouvoir déclencher la backdoor
  • Le payload de la backdoor est placé dans la valeur N de la clé de signature CA d’un certificat SSH, et construit le type de requête avec a * b + c ; le type 2 exécute une commande terminée par un octet nul via system()
  • La CLI de démonstration montre le flux de connexion à un serveur SSH vulnérable pour y exécuter une commande, et une exploitation réussie ne génère pas de logs de niveau INFO ou supérieur

Portée et composition de xzbot

  • xzbot est un projet destiné à explorer la backdoor xz, CVE-2024-3094
  • Le dépôt comprend quatre éléments
    • honeypot : un faux serveur vulnérable pour détecter les tentatives d’exploit
    • ed448 patch : un patch de liblzma.so pour utiliser sa propre clé publique ED448
    • backdoor format : une description du format du payload de la backdoor
    • backdoor demo : une CLI qui déclenche une RCE en supposant que l’on connaît la clé privée ED448

Honeypot : détection des tentatives via un patch OpenSSH

  • openssh.patch est un patch simple à appliquer à OpenSSH pour consigner les tentatives de connexion utilisant une valeur N de clé publique correspondant au format de la backdoor
  • Le flux consiste à cloner openssh-portable, puis à appliquer le patch et exécuter autoreconf, configure et make
  • Les tentatives de connexion apparaissent dans les logs sshd sous la forme xzbot: magic 1 [preauth] avec les octets du payload

Patch de clé publique ED448

  • La backdoor utilise une clé publique ED448 codée en dur pour vérifier la signature et déchiffrer le payload
  • Remplacer cette clé par une clé détenue par l’utilisateur permet de déclencher la backdoor
  • Le dépôt fournit à la fois la clé publique ED448 de l’attaquant et une valeur de clé publique de remplacement générée avec seed=0
  • La première étape consiste à préparer l’objet partagé liblzma.so.5.6.1 contenant la backdoor
    • Un snapshot Debian de xz-utils 5.6.1-1 est donné comme source d’exemple
    • Après installation de pwntools, l’exécution de patch.py liblzma.so.5.6.1 génère liblzma.so.5.6.1.patch
    • Il faut ensuite exécuter sshd avec l’objet partagé modifié liblzma.so.5.6.1.patch
  • Le répertoire assets contient des exemples

Format du payload de la backdoor

  • La backdoor peut être déclenchée lors d’une connexion avec un certificat SSH en plaçant le payload dans la valeur N de la clé de signature CA
  • Ce payload doit être chiffré et signé avec la clé ED448 de l’attaquant
  • La structure externe se compose des champs suivants
    • a : 32 bits
    • b : 32 bits
    • c : 64 bits
    • ciphertext : 240 octets
  • Le type de requête est dérivé de a * b + c
    • Si la valeur est supérieure à 3, la backdoor ignore le traitement
    • Type 1 : usage inconnu, attend 0 octet
    • Type 2 : exécute via system() un payload terminé par un octet nul
    • Type 3 : usage inconnu, attend 48 octets de données de signature
  • ciphertext est chiffré en chacha20 en utilisant comme clé symétrique les 32 premiers octets de la clé publique ED448
    • Par conséquent, les tentatives d’exploit peuvent être déchiffrées avec la clé de 32 octets fournie
  • À l’intérieur du ciphertext déchiffré se trouvent une signature de 114 octets, les champs 1 bit x et y, une longueur, la chaîne de commande, etc.
    • Définir x ou y entraîne des chemins de code légèrement différents
  • La signature est une signature ED448 RFC-8032
    • L’entrée comprend une valeur magic 32 bits, un champ de 5 octets avant la commande, éventuellement length octets de la commande, et les 32 premiers octets du hash SHA-256 de la hostkey du serveur

CLI de démonstration de l’exploit

  • La CLI s’installe avec Go
    • go install github.com/amlweems/xzbot@latest
  • xzbot -h affiche trois options principales
    • -addr : adresse du serveur SSH, valeur par défaut 127.0.0.1:2222
    • -seed : seed ED448 devant correspondre à la clé de la backdoor xz, valeur par défaut 0
    • -cmd : commande à exécuter via system(), valeur par défaut id > /tmp/.xz
  • L’exemple se connecte à un serveur SSH vulnérable sur 127.0.0.1:2222 et exécute la commande id > /tmp/.xz
  • En plaçant un watchpoint à l’emplacement de l’appel à system() sur le serveur vulnérable, on peut voir le processus sshd exécuter id > /tmp/.xz
  • Après exécution, l’exemple montre que /tmp/.xz contient la sortie uid=0(root) gid=0(root) groups=0(root)

Arbre des processus et caractéristiques des logs

  • L’arbre des processus d’une connexion SSH normale mène de sshd à la session utilisateur puis au shell
  • L’exemple d’exécution de la backdoor, après xzbot -cmd 'sleep 60', fait apparaître sshd: root [priv], sshd: root [net], sh -c sleep 60, sleep 60
  • Une exploitation réussie ne crée pas d’entrée de log de niveau INFO ou supérieur

Références

1 commentaires

 
GN⁺ 2024-04-02
Commentaires sur Hacker News
  • Le fait qu’il ne s’agisse pas d’une exécution de code à distance exploitable par n’importe qui, mais qu’elle nécessite la clé privée de l’attaquant, est assez intéressant
    Ironiquement, cela ressemble à une vulnérabilité très soucieuse de la sécurité

    • L’intention initiale était sans doute de prolonger la durée de vie de la backdoor
      S’ils avaient laissé un énorme trou accessible à tout le monde, il aurait été rapidement découvert et colmaté ; sans dégradation des performances, il aurait pu survivre discrètement longtemps justement parce qu’il n’était pas largement exploitable
    • Si on le voit comme une attaque soutenue par un État, l’idée d’implanter une vulnérabilité sûre dans un système que ses propres citoyens peuvent aussi utiliser a beaucoup de sens
      L’ensemble des contributions à xz semble au final avoir eu pour but d’introduire cette backdoor, avec par exemple la création d’un framework de test capable de dissimuler une charge utile malveillante
      Avant de travailler sur xz, il avait aussi contribué à libarchive de BSD, où une vulnérabilité est apparue
    • Cela ressemble vraiment à un exploit soutenu par un État
      La conception et l’exécution étaient extrêmement sophistiquées, et le fait que ce soit un problème de performances qui ait conduit à sa découverte donne presque l’impression d’un pur coup de chance
    • C’est ce qu’on appelle NOBUS : https://en.wikipedia.org/wiki/NOBUS
    • J’ai l’impression que la signature de la charge utile inclut la clé hôte SSH de la cible ; je me demande si c’est bien ça
      Si oui, on ne peut pas l’envoyer massivement à des serveurs au hasard, et le simple fait de l’envoyer à un hôte donné a déjà un coût de calcul non négligeable
  • Cette affaire ne m’est pas sortie de la tête tout le week-end
    Le mécanisme est fascinant, c’est une superbe collection de techniques d’obfuscation, et la partie ingénierie sociale est une histoire honteusement familière pour les mainteneurs open source
    Le point le plus intéressant est le choix de mauvaises données de test comme vecteur d’attaque : en préparant une bonne archive puis en la manipulant structurellement avant de l’utiliser comme mauvaise donnée pour du fuzz testing, tout le reste devient énormément plus simple
    À l’avenir, ce genre de manipulation devrait sans doute apparaître dans les graphes de motifs binaires
    Le reste des techniques relevait surtout d’une obfuscation assez classique une fois la charge utile fixée, mais le coup le plus brillant a été de pouvoir ajouter discrètement, selon le même modèle, des « correctifs » à d’autres fichiers de test, voire une toute nouvelle backdoor sans éveiller les soupçons
    Le fait que GitHub ait masqué puis supprimé le dépôt n’a absolument pas aidé et a au contraire gêné l’analyse de l’incident

    • Cela m’a rendu méfiant envers les dépendances au moment de la compilation des outils open source que nous utilisons
      J’ai découvert que cette dépendance semblait avoir une préférence marquée pour xz et, s’il n’était pas installé, allait jusqu’à l’installer sur la machine hôte comme s’il s’agissait d’une simple commodité
      Elle n’a pas ce comportement avec les autres dépendances, ce qui paraît étrange
      Ce genre d’opération au long cours fait peur, et tant que le « mal » n’est pas réellement exécuté, il est difficile de savoir ce qui est malveillant et ce qui est simplement bizarre
    • L’une des causes profondes semble être l’ajout de fichiers binaires dans le dépôt pour servir d’entrées de test
      Surtout s’il s’agit de fichiers de « déchets binaires » destinés à prouver l’échec d’un test, c’est un excellent endroit pour cacher du contenu malveillant
    • En supprimant le dépôt, on a fini par laisser seuls les attaquants avec accès au code et au savoir-faire
  • Il est très impressionnant de voir à quelle vitesse la communauté, et amlweems en particulier, a pu implémenter et documenter un code de preuve de concept
    S’il n’y a pas d’autres vulnérabilités dans les fonctions cryptographiques ou de chargement de la charge utile, cela n’a peut-être pas non plus ouvert la faille de sécurité à tous les autres attaquants tant que la clé n’est pas compromise
    L’étape suivante consiste à trouver comment détecter les distributions vulnérables, ce qui ne semble pas simple, et il serait peut-être possible d’ajouter dans l’upstream un moyen de surveiller si quelqu’un sonde activement des serveurs SSH avec la clé codée en dur

    • Ce n’est pas l’exploit d’origine, mais une preuve de concept avec une clé modifiée
      Une preuve de concept pour la version d’origine nécessiterait la clé privée non publiée de l’attaquant
    • Sans la clé privée de l’attaquant, détecter à distance sur le réseau des distributions vulnérables semble moins difficile qu’impossible
      Le mieux qu’on puisse faire serait un benchmarking plus fin, mais il est impossible de savoir si un hôte sur Internet est lent parce qu’il est vulnérable, parce qu’il est loin, ou parce que la machine elle-même est lente
      On n’a pas non plus accès au temps qu’ont pris les tentatives de connexion passées à cet hôte, et il y a aussi les variations de routage
  • Je me demande si quelqu’un a fait tourner cette preuve de concept contre des outils de détection de comportements anormaux des processus
    Cela viserait des produits comme Carbon Black, AWS GuardDuty ou Sysdig, et cela semble être un cas presque idéal pour tester si quelqu’un l’aurait détecté assez rapidement s’il avait été réellement déployé

    • J’imagine que tout dépend de la mesure dans laquelle l’exploit imite un comportement de compression légitime ou se cache en son sein
      GuardDuty ne regarde pas les processus comme un EDR tel que CrowdStrike ou Carbon Black, donc cela semble difficile à détecter ; Sysdig observe surtout les conteneurs et l’infrastructure cloud, donc il paraît lui aussi peu susceptible de détecter l’exploit en tant que tel
      En revanche, il pourrait y avoir des signes anormaux dans les actions ultérieures de l’acteur malveillant après l’élévation de privilèges
      En fin de compte, ce qui a le plus de chances de détecter l’exploit lui-même serait probablement un EDR surveillant les processus sur les endpoints, ou une évaluation de la supply chain logicielle surveillant les problèmes de sécurité dans les logiciels libres et open source en amont
      Fait intéressant, cela mène à un sujet de sécurité plus large
      Les équipes de développement peuvent ne pas aimer déployer des EDR sur les serveurs à cause des baisses de performances et des problèmes d’expérience utilisateur liés aux mesures d’isolement, et elles peuvent aussi ne pas aimer les politiques qui limitent l’usage de logiciels libres et open source
      Cet exploit frappe en plein cœur une « vulnérabilité » organisationnelle, ce qui crée, selon le contexte, des arguments à la fois pour maintenir l’exposition et pour la corriger
    • Sysdig a publié un billet vendredi
      « Une méthode de détection à l’exécution consiste à surveiller si SSHD charge une bibliothèque malveillante. Ces bibliothèques partagées incluent souvent une version dans leur nom de fichier »
      Le billet contient aussi de vraies règles de détection que je n’ai pas vues chez d’autres éditeurs de sécurité
      https://sysdig.com/blog/cve-2024-3094-detecting-the-sshd-bac...
    • J’ai l’impression que toute cette catégorie de produits est globalement composée de produits de sécurité surtout basés sur du vent
  • J’ai mal lu le lien ci-dessous, et je laisse le contenu d’origine à titre d’archive
    En regardant plus bas dans le même fil d’e-mails, quelqu’un disait que la personne ayant commité la backdoor semblait aussi avoir récemment fait des contributions au noyau, mais l’analyse d’origine elle-même est vraiment excellente, donc ce genre de texte vaut la peine d’être lu
    https://www.openwall.com/lists/oss-security/2024/03/29/10

    • Cette série de patchs a été envoyée non pas par Jia Tan mais par Lasse
      Lasse lui-même a aussi dit qu’il n’y avait absolument aucune urgence et que cela n’entrerait pas dans cette fenêtre de merge, et personne de raisonnable n’accuse Lasse d’être un acteur malveillant
    • Jusqu’à preuve du contraire, Lasse Collin n’est pas Jia Tan
    • La série de patchs mentionnée n’a toujours pas été intégrée au noyau
    • C’est peut-être une coïncidence, mais JiaT75 ressemble beaucoup au code de transpondeur 7500, qui signifie détournement en aviation
  • Cette affaire a un nombre absurde de points communs avec l’affaire Audacity d’il y a quelques années
    Cookie guy affirmait avoir été poignardé et que la police fédérale était impliquée dans l’affaire, ce qui suggère qu’elle pouvait être liée à des acteurs bien plus importants que 4chan
    À l’époque, beaucoup pensaient que seul Muse Group était impliqué, mais c’était peut-être en réalité un acteur étatique russe
    Avant cela, il avait affirmé qu’Audacity contenait beaucoup de télémétrie et des backdoors, qu’il avait supprimées dès le premier commit après le fork
    Il est peut-être possible qu’Audacity ait réellement eu une backdoor, donc il faudrait vérifier le code source

    • Il faut faire attention, APT28 est assez dangereux
      Ces temps-ci, ils combinent leurs opérations avec APT29, et à ta place je n’irais pas réveiller cozy bear
    • C’est qui, Cookie guy ?
  • Sans le honeypot openssh.patch au moment de la compilation https://github.com/amlweems/xzbot/blob/main/openssh.patch, je me demande comment l’exploit réel faisait cela à l’exécution
    La chaîne était opensshd -> notification systemd -> xz inclus comme dépendance transitoire, mais une fois liblzma.so.5.6.1 chargé en mémoire, j’aimerais comprendre comment il remontait jusqu’à openssh_RSA_verify pour y placer un hook ou un patch

    • Au chargement de liblzma, il patche l’adresse du code malveillant dans la GOT de l’ELF
      S’il est chargé avant libcrypto, il enregistre un gestionnaire d’audit de symboles, ce qui semble probablement être une fonctionnalité spécifique à glibc, et cela lui permet de différer le patch de la GOT jusqu’au moment où les symboles de libcrypto sont résolus
    • C’est un ifunc
  • Je me demande si quelqu’un sait si cet exploit ne fonctionnait que lorsqu’une connexion SSH arrivait
    La liste des chaînes sur GitHub contient DISPLAY et WAYLAND_DISPLAY
    https://gist.github.com/q3k/af3d93b6a1f399de28fe194add452d01
    Cela n’a pas de lien évident avec SSH, donc il est possible qu’il fasse aussi quelque chose en l’absence de connexion
    Cela peut être important pour ceux qui supposent être en sécurité parce qu’ils ont exécuté le code sans exposer leur serveur SSH à Internet

    • C’est probablement un kill switch destiné à empêcher l’exploit de fonctionner si un terminal est ouvert ou s’il s’exécute dans une session GUI
      Autrement dit, c’est un mécanisme pour éviter les situations où quelqu’un essaie de le détecter, de le reproduire ou de le déboguer
    • Cela peut aussi être lié au transfert de session X11
      Si on ne le désactive pas en se connectant à une machine non fiable, cela devient souvent une faille de sécurité côté client
  • Quand on dit qu’« un exploitation réussie ne génère pas d’entrée de log », je me demande si cela signifie que, si cet exploit n’avait pas été détecté, un attaquant aurait pu exécuter des commandes arbitraires en root sur un hôte compromis sans la moindre ligne de log sshd correspondant à cette « connexion »

    • Oui
      L’exécution de code à distance se produit durant la phase de connexion, avant que les logs ne soient écrits
    • Il y aurait quand même eu du trafic SSH sans login correspondant
      Je me demande quel type de détection d’anomalie aurait pu repérer cela
  • Je me demande si séparer les fichiers de test dans un dépôt distinct, de sorte qu’ils ne puissent pas être utilisés au moment du build, aurait rendu cette attaque plus difficile
    L’idée est que tout ce qui peut influer sur le build doit être lisible par un humain

    • « Tout ce qui peut influer sur le build doit être lisible par un humain » est un bon principe à adopter de manière générale
      Il faut traiter cette attaque comme un accident d’avion et introduire de nouvelles règles pour réduire les chances qu’elle réussisse à nouveau
      Même si on ne peut pas vérifier chaque contributeur individuellement, il devrait être facile de séparer des données de test trop bruyantes