2 points par GN⁺ 11 일 전 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • L’intégration SSH utilise des escape sequences du terminal pour communiquer avec le shell distant, et à cause de cette architecture, une sortie terminal ordinaire peut elle aussi être interprétée comme le protocole conductor
  • Le problème central est un échec de confiance : non seulement le véritable conductor distant, mais aussi des fichiers malveillants, bannières, MOTD ou réponses serveur peuvent se faire passer pour conductor via de faux DCS 2000p et OSC 135
  • Le simple fait d’exécuter cat readme.txt peut suffire : si un faux transcript conductor est rendu, iTerm2 enchaîne lui-même le flux getshell · pythonversion · run(...), et la sortie d’attaque n’a plus qu’à imiter les réponses
  • L’exploit tire parti d’une confusion autour du PTY : une commande base64 écrite dans le PTY tombe en entrée texte clair du shell local lorsqu’il n’y a pas de véritable SSH conductor, et peut être exécutée quand le dernier chunk est interprété comme le chemin ace/c+aliFIo
  • Le correctif a été intégré dans le commit du 31 mars a9e745993c2e2cbb30b884a16617cd5495899f86, mais au moment de la publication il n’était pas encore inclus dans une stable release, créant une fenêtre d’exposition avant la diffusion du patch

Contexte de l’intégration SSH d’iTerm2

  • L’iTerm2 SSH integration est une fonctionnalité conçue pour mieux comprendre les sessions distantes, avec un fonctionnement basé sur l’envoi d’un petit script helper appelé conductor sur le shell distant
    • démarrage de l’intégration SSH via it2ssh
    • transmission de conductor, script distant de bootstrap, via la session SSH existante
    • ce script distant joue ensuite le rôle de pair du protocole iTerm2
  • iTerm2 et conductor distant ne communiquent pas comme un service réseau classique, mais en s’échangeant des escape sequences sur les E/S du terminal
    • détection du shell de connexion
    • vérification de la présence de Python
    • changement de répertoire
    • upload de fichiers
    • exécution de commandes

Fonctionnement du PTY

  • Les émulateurs de terminal modernes sont des versions logicielles des anciens terminaux matériels, chargés de l’affichage, de l’entrée clavier et de l’interprétation des séquences de contrôle du terminal
  • Les shells et programmes en ligne de commande s’attendent toujours à un périphérique ressemblant à un vrai terminal, d’où l’usage d’un PTY fourni par l’OS
    • le PTY est un pseudoterminal placé entre l’émulateur de terminal et le processus au premier plan
  • Dans une session SSH classique, iTerm2 écrit des octets dans le PTY, puis le processus au premier plan, ssh, les transmet à la machine distante, où conductor les lit sur stdin
  • Quand iTerm2 envoie une commande au conductor distant, localement cela revient donc à écrire des octets dans le PTY

Protocole conductor

  • Le protocole de transport de l’intégration SSH repose sur des escape sequences du terminal
  • Deux éléments sont centraux
    • DCS 2000p sert à hooker le SSH conductor
    • OSC 135 sert aux messages conductor pré-encapsulés
  • Au niveau du code source, DCS 2000p amène iTerm2 à créer un conductor parser, qui traite ensuite les messages OSC 135
    • begin <id>
    • lignes de sortie de commande
    • end <id> <status> r
    • unhook
  • Un conductor distant légitime peut donc communiquer avec iTerm2 uniquement par la sortie terminal

Vulnérabilité principale

  • La vulnérabilité est fondamentalement un échec de confiance : iTerm2 accepte comme protocole SSH conductor des sorties terminal qui ne proviennent pas d’une véritable session conductor de confiance
  • En conséquence, une sortie terminal non fiable peut se faire passer pour un conductor distant
    • fichier malveillant
    • réponse serveur
    • bannière
    • MOTD
  • Une entrée d’attaque peut afficher un faux hook DCS 2000p et de fausses réponses OSC 135, et iTerm2 se comporte alors comme si un véritable échange d’intégration SSH était en cours

Fonctionnement de l’exploit

  • Le fichier d’exploit contient un faux transcript conductor
  • Quand l’utilisateur exécute cat readme.txt, iTerm2 rend le fichier, mais celui-ci ne contient pas un simple texte : il inclut aussi
    • une fausse ligne DCS 2000p signalant une fausse session conductor
    • de faux messages OSC 135 répondant aux requêtes d’iTerm2
  • Une fois le hook accepté, iTerm2 lance le workflow normal de conductor : dans le code amont, Conductor.start() envoie immédiatement getshell(), puis, en cas de succès, pythonversion()
  • L’attaque n’a pas besoin d’injecter ces requêtes : c’est iTerm2 qui les émet de lui-même, et la sortie malveillante n’a qu’à imiter les réponses

Déroulement de la machine à états

  • Les faux messages OSC 135 sont minimaux, mais ordonnés avec précision
    • début du corps de commande pour getshell
    • renvoi d’une ligne ressemblant à une sortie de détection du shell
    • fin réussie de cette commande
    • début du corps de commande pour pythonversion
    • fin en échec de cette commande
    • unhook
  • Ce simple enchaînement suffit pour faire entrer iTerm2 dans son chemin de repli normal, puis lui faire considérer que le workflow d’intégration SSH a été suffisamment mené à bien pour passer à l’étape suivante
  • L’étape suivante consiste à construire puis envoyer la commande run(...)

Rôle de sshargs

  • Le faux hook DCS 2000p contient plusieurs champs, dont sshargs, contrôlé par l’attaquant
  • Cette valeur est ensuite utilisée par iTerm2 comme matière première de commande lors de la construction de sa requête run ... pour conductor
  • L’exploit choisit sshargs de façon à ce qu’au moment où iTerm2 encode en base64 les données suivantes
    • run <padding><magic-bytes>
  • le dernier chunk de 128 octets devienne ace/c+aliFIo
  • Cette chaîne n’est pas arbitraire : elle est choisie pour satisfaire simultanément deux conditions
    • être une sortie valide du chemin d’encodage de conductor
    • être un nom de chemin relatif valide

La confusion PTY qui rend l’exploit possible

  • Dans une session normale d’intégration SSH, iTerm2 écrit dans le PTY des commandes conductor encodées en base64, puis ssh les transmet au conductor distant
  • Dans le scénario d’exploit, iTerm2 écrit de la même manière les commandes dans le PTY, sauf qu’en l’absence de véritable SSH conductor, le shell local les reçoit comme une entrée en texte clair
  • Dans la session enregistrée, on observe
    • getshell sous forme base64
    • pythonversion sous forme base64
    • puis une longue payload run ... encodée en base64
    • dont le dernier chunk est ace/c+aliFIo
  • Les chunks précédents échouent comme commandes sans signification, mais le dernier s’exécute si ce chemin existe localement et est exécutable

Procédure de reproduction

  • Le PoC original basé sur des fichiers peut être reproduit avec genpoc.py
    • python3 genpoc.py
    • unzip poc.zip
    • cat readme.txt
  • Cette procédure génère deux fichiers
    • un script helper exécutable nommé ace/c+aliFIo
    • un readme.txt contenant les séquences malveillantes DCS 2000p et OSC 135
  • Le premier fichier pousse iTerm2 à communiquer avec le faux conductor, et le second fournit au shell la cible réellement exécutée à l’arrivée du dernier chunk
  • Pour que l’exploit réussisse, cat readme.txt doit être exécuté dans le répertoire où se trouve ace/c+aliFIo, afin que le dernier chunk contrôlé par l’attaquant soit interprété comme un chemin réellement exécutable

Divulgation et calendrier du patch

  • signalement du bug à iTerm2 le 30 mars
  • correctif finalisé le 31 mars dans le commit a9e745993c2e2cbb30b884a16617cd5495899f86
  • au moment de la rédaction, le correctif n’était toujours pas inclus dans une stable release
  • après l’intégration du commit de correctif, une tentative de reconstruction complète de l’exploit à partir du seul patch a été menée
    • les prompts utilisés figurent dans prompts.md
    • le résultat est genpoc2.py
    • son fonctionnement est très proche de genpoc.py

Question sur le moment de la divulgation

  • La divulgation est intervenue avant que le correctif n’atteigne une stable release, ouvrant une période où la plupart des utilisateurs ne pouvaient pas réellement être protégés alors même que la vulnérabilité devenait publique
  • Une telle tension sur le calendrier de publication nécessite une justification claire
  • Deux semaines, c’est à la fois trop court pour espérer une diffusion significative du correctif, et trop court aussi pour justifier qu’une divulgation anticipée était nécessaire pour forcer la réponse
  • En pratique, cela a créé une fenêtre de divulgation où la faille était largement connue alors que le correctif n’était pas encore accessible aux utilisateurs qui en avaient réellement besoin
  • Une meilleure option aurait été d’attendre que la version corrigée arrive réellement chez les utilisateurs, ou d’expliquer clairement pourquoi une exposition anticipée était nécessaire, mais aucune de ces deux conditions n’a été remplie

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.