Xzbot : notes, honeypot et démo d’exploit pour la backdoor xz
(github.com/amlweems)- 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
sshdles 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 viasystem() - 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.sopour 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écuterautoreconf,configureetmake - Les tentatives de connexion apparaissent dans les logs
sshdsous la formexzbot: 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.1contenant la backdoor- Un snapshot Debian de
xz-utils 5.6.1-1est donné comme source d’exemple - Après installation de
pwntools, l’exécution depatch.py liblzma.so.5.6.1génèreliblzma.so.5.6.1.patch - Il faut ensuite exécuter
sshdavec l’objet partagé modifiéliblzma.so.5.6.1.patch
- Un snapshot Debian de
- 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 bitsb: 32 bitsc: 64 bitsciphertext: 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
ciphertextest 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
ciphertextdéchiffré se trouvent une signature de 114 octets, les champs 1 bitxety, une longueur, la chaîne de commande, etc.- Définir
xouyentraîne des chemins de code légèrement différents
- Définir
- 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
lengthoctets de la commande, et les 32 premiers octets du hash SHA-256 de la hostkey du serveur
- L’entrée comprend une valeur magic 32 bits, un champ de 5 octets avant la commande, éventuellement
CLI de démonstration de l’exploit
- La CLI s’installe avec Go
go install github.com/amlweems/xzbot@latest
xzbot -haffiche trois options principales-addr: adresse du serveur SSH, valeur par défaut127.0.0.1:2222-seed: seed ED448 devant correspondre à la clé de la backdoor xz, valeur par défaut0-cmd: commande à exécuter viasystem(), valeur par défautid > /tmp/.xz
- L’exemple se connecte à un serveur SSH vulnérable sur
127.0.0.1:2222et exécute la commandeid > /tmp/.xz - En plaçant un watchpoint à l’emplacement de l’appel à
system()sur le serveur vulnérable, on peut voir le processussshdexécuterid > /tmp/.xz - Après exécution, l’exemple montre que
/tmp/.xzcontient la sortieuid=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îtresshd: 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
1 commentaires
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é
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
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
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
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
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
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
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
Une preuve de concept pour la version d’origine nécessiterait la clé privée non publiée de l’attaquant
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é
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
« 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 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
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
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
Ces temps-ci, ils combinent leurs opérations avec APT29, et à ta place je n’irais pas réveiller cozy bear
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 foisliblzma.so.5.6.1chargé en mémoire, j’aimerais comprendre comment il remontait jusqu’àopenssh_RSA_verifypour y placer un hook ou un patchS’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
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
DISPLAYetWAYLAND_DISPLAYhttps://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
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
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 »
L’exécution de code à distance se produit durant la phase de connexion, avant que les logs ne soient écrits
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
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