2 Punkte von GN⁺ 11 일 전 | 1 Kommentare | Auf WhatsApp teilen
  • Die SSH integration verwendet Terminal-Escape-Sequenzen, um mit der Remote-Shell zu kommunizieren, und durch diese Struktur kann auch gewöhnliche Terminalausgabe wie das conductor-Protokoll interpretiert werden
  • Das Kernproblem ist ein Vertrauensfehler: Auch bösartige Dateien, Banner, MOTD oder Serverantworten, die nicht vom echten Remote-conductor stammen, können sich über gefälschte DCS 2000p- und OSC 135-Sequenzen wie conductor verhalten
  • Schon das Ausführen von cat readme.txt reicht aus: Wenn ein gefälschtes conductor-Transcript gerendert wird, durchläuft iTerm2 den Ablauf getshell · pythonversion · run(...) selbstständig, und die Angriffsausgabe muss lediglich Antworten vortäuschen
  • Der Exploit nutzt eine Verwechslung aus, bei der in das PTY geschriebene Base64-Befehle ohne echten SSH-conductor als lokale Shell-Klartexteingabe ankommen; ausführbar wird dies, wenn der letzte Chunk als Pfad ace/c+aliFIo interpretiert wird
  • Der Fix wurde im Commit vom 31. März a9e745993c2e2cbb30b884a16617cd5495899f86 eingepflegt, war zum Zeitpunkt der Veröffentlichung aber noch nicht in einem stable release enthalten, wodurch vor der Verteilung des Patches ein Schutzfenster offen blieb

Hintergrund der SSH-Integration in iTerm2

  • Die iTerm2 SSH integration ist eine Funktion, um Remote-Sitzungen besser zu verstehen; dazu wird ein kleines Hilfsskript namens conductor auf die Remote-Shell hochgeladen
    • Start der SSH-Integration über it2ssh
    • Übertragung des Remote-Bootstrap-Skripts conductor über die bestehende SSH-Sitzung
    • Dieses Remote-Skript übernimmt die Gegenstelle des iTerm2-Protokolls
  • iTerm2 und der Remote-conductor kommunizieren nicht als gewöhnlicher Netzwerkdienst, sondern tauschen Escape-Sequenzen über Terminal-I/O aus
    • Login-Shell erkennen
    • Vorhandensein von Python prüfen
    • Verzeichnis wechseln
    • Dateien hochladen
    • Befehle ausführen

Funktionsweise von PTY

  • Moderne Terminalemulatoren sind Software-Versionen früherer Hardware-Terminals und übernehmen Bildschirmausgabe, Tastatureingabe und die Interpretation von Terminal-Steuersequenzen
  • Shells und Kommandozeilenprogramme erwarten weiterhin ein Gerät, das wie ein echtes Terminal aussieht; deshalb stellt das Betriebssystem ein PTY bereit
    • Ein PTY ist ein Pseudoterminal zwischen Terminalemulator und Vordergrundprozess
  • In einer normalen SSH-Sitzung schreibt iTerm2 Bytes in das PTY, der Vordergrundprozess ssh leitet sie an die Remote-Maschine weiter, und der Remote-conductor liest sie von stdin
  • Wenn iTerm2 Befehle an den Remote-conductor sendet, geschieht das lokal letztlich durch das Schreiben von Bytes in das PTY

Das conductor-Protokoll

  • Als Transportmedium für das SSH-Integrationsprotokoll werden Terminal-Escape-Sequenzen verwendet
  • Es gibt zwei zentrale Elemente
    • DCS 2000p dient zum Hooken des SSH-conductor
    • OSC 135 dient für Pre-Framer-conductor-Nachrichten
  • Auf Quellcodeebene sorgt DCS 2000p dafür, dass iTerm2 einen conductor parser erstellt, der anschließend OSC 135-Nachrichten verarbeitet
    • begin <id>
    • command output lines
    • end <id> <status> r
    • unhook
  • Ein legitimer Remote-conductor kann allein über Terminalausgabe mit iTerm2 kommunizieren

Die zentrale Schwachstelle

  • Das Wesen der Schwachstelle ist ein Vertrauensfehler: Selbst Terminalausgabe, die nicht aus einer echten vertrauenswürdigen conductor-Sitzung stammt, wird von iTerm2 als SSH-conductor-Protokoll akzeptiert
  • Dadurch kann nicht vertrauenswürdige Terminalausgabe einen Remote-conductor vortäuschen
    • bösartige Dateien
    • Serverantworten
    • Banner
    • MOTD
  • Die Angabeeingabe kann einen gefälschten DCS 2000p-Hook und gefälschte OSC 135-Antworten ausgeben; in diesem Fall verhält sich iTerm2 so, als würde ein echter SSH-integration-Austausch stattfinden

So funktioniert der Exploit

  • Die Exploit-Datei enthält ein gefälschtes conductor-Transcript
  • Wenn der Nutzer cat readme.txt ausführt, rendert iTerm2 die Datei, doch sie enthält nicht nur Text, sondern auch die folgenden Elemente
    • eine gefälschte DCS 2000p-Zeile, die eine gefälschte conductor-Sitzung ankündigt
    • gefälschte OSC 135-Nachrichten, die auf iTerm2-Anfragen antworten
  • Wird der Hook akzeptiert, startet iTerm2 den normalen conductor-Workflow; im Upstream-Quellcode sendet Conductor.start() sofort getshell() und danach bei Erfolg pythonversion()
  • Der Angriff muss diese Anfragen nicht selbst injizieren, denn iTerm2 stellt sie von sich aus; die bösartige Ausgabe muss lediglich Antworten vortäuschen

Ablauf der State Machine

  • Die gefälschten OSC 135-Nachrichten sind minimal, aber in der exakt richtigen Reihenfolge aufgebaut
    • Start des Command-Bodys für getshell
    • Rückgabe einer Zeile, die wie Shell-Erkennungsausgabe aussieht
    • erfolgreiches Ende dieses Befehls
    • Start des Command-Bodys für pythonversion
    • fehlgeschlagenes Ende dieses Befehls
    • unhook
  • Schon dieser Ablauf reicht aus, damit iTerm2 in den normalen Fallback-Pfad eintritt und anschließend annimmt, der SSH-integration-Workflow sei weit genug abgeschlossen, um mit dem nächsten Schritt fortzufahren
  • Der nächste Schritt ist das Zusammenbauen und Senden des Befehls run(...)

Die Rolle von sshargs

  • Der gefälschte DCS 2000p-Hook enthält mehrere Felder, darunter die vom Angreifer kontrollierten sshargs
  • Dieser Wert wird später von iTerm2 als Baustein des Befehls verwendet, wenn die run ...-Anfrage des conductor zusammengesetzt wird
  • Der Exploit wählt sshargs so, dass iTerm2 die folgenden Daten Base64-kodiert
    • run <padding><magic-bytes>
  • und der letzte 128-Byte-Chunk ace/c+aliFIo ergibt
  • Dieser String ist kein Zufallswert, sondern wurde so gewählt, dass er gleichzeitig zwei Bedingungen erfüllt
    • eine gültige Ausgabe des conductor-Kodierungspfads
    • ein gültiger relativer Pfadname

Die PTY-Verwechslung, die den Exploit ermöglicht

  • In einer normalen SSH-integration-Sitzung schreibt iTerm2 Base64-kodierte conductor-Befehle in das PTY, und ssh leitet sie an den Remote-conductor weiter
  • Im Exploit-Fall schreibt iTerm2 die Befehle genauso in das PTY, doch weil kein echter SSH-conductor existiert, empfängt die lokale Shell sie als Klartexteingabe
  • In der aufgezeichneten Sitzung ist Folgendes zu sehen
    • getshell erscheint in Base64-Form
    • pythonversion erscheint in Base64-Form
    • danach folgt ein langes Base64-kodiertes run ...-Payload
    • der letzte Chunk ist ace/c+aliFIo
  • Die vorherigen Chunks schlagen als bedeutungslose Befehle fehl; der letzte Chunk funktioniert, wenn dieser Pfad lokal existiert und ausführbar ist

Schritte zur Reproduktion

  • Das ursprüngliche dateibasierte PoC lässt sich mit genpoc.py reproduzieren
    • python3 genpoc.py
    • unzip poc.zip
    • cat readme.txt
  • Dadurch werden zwei Dateien erzeugt
    • ein ausführbares Hilfsskript namens ace/c+aliFIo
    • readme.txt mit den bösartigen Sequenzen DCS 2000p und OSC 135
  • Die erste Datei bringt iTerm2 dazu, mit dem gefälschten conductor zu kommunizieren, und die zweite liefert das Ziel, das die Shell beim Eintreffen des letzten Chunks tatsächlich ausführt
  • Damit der Exploit erfolgreich ist, muss cat readme.txt in dem Verzeichnis ausgeführt werden, in dem sich ace/c+aliFIo befindet, damit der letzte vom Angreifer geformte Chunk als tatsächlich ausführbarer Pfad interpretiert wird

Offenlegung und Patch-Zeitplan

  • Fehler am 30. März an iTerm2 gemeldet
  • Fix am 31. März im Commit a9e745993c2e2cbb30b884a16617cd5495899f86 abgeschlossen
  • Zum Zeitpunkt des Schreibens war der Fix noch nicht in einem stable release enthalten
  • Nach Einspielen des Patch-Commits wurde versucht, den Exploit ausschließlich auf Basis des Patches von Grund auf neu zu konstruieren
    • die Prompts dazu in prompts.md
    • das Ergebnis ist genpoc2.py
    • funktioniert sehr ähnlich wie genpoc.py

Kritik am Veröffentlichungszeitpunkt

  • Die Offenlegung erfolgte, bevor der Fix eine stable release erreicht hatte, wodurch ein Zustand entstand, in dem die meisten Nutzer praktisch noch nicht geschützt waren, während die Schwachstelle bereits bekannt wurde
  • Für einen solchen Zielkonflikt beim Veröffentlichungszeitpunkt braucht es eine klare Rechtfertigung
  • Zwei Wochen sind zu kurz, um mit sinnvoller Verbreitung zu rechnen, aber auch zu kurz, um eine frühe Offenlegung mit dem Erzwingen von Gegenmaßnahmen zu rechtfertigen
  • So entstand letztlich ein Offenlegungsfenster, in dem die Schwachstelle weithin bekannt war, die korrigierte Version für die tatsächlich betroffenen Nutzer aber realistisch noch nicht verfügbar war
  • Eine bessere Option wäre gewesen, bis zur tatsächlichen Auslieferung der korrigierten Version an Nutzer zu warten oder klar zu begründen, warum eine frühe Offenlegung nötig war; beides wurde hier nicht erfüllt

1 Kommentare

 
GN⁺ 11 일 전
Hacker-News-Kommentare
  • Ich habe mich gefragt, warum das jetzt veröffentlicht wurde, obwohl für die stabile Version noch kein Patch erschienen ist. Seit der Meldung an Upstream sind erst 18 Tage vergangen, und der Blogpost war deutlich detaillierter als der veröffentlichte Commit, was meiner Meinung nach die praktische Ausnutzbarkeit erhöht hat. Ich habe zwar bestätigt, dass der Autor allein mit dem Upstream-Commit und einem LLM einen Exploit bauen konnte, trotzdem finde ich, dass dieser Beitrag die Sichtbarkeit der Schwachstelle weiter erhöht hat

    • Ich bin nicht die Person, die die Schwachstelle entdeckt hat, sondern der Autor des Blogposts. Schon allein anhand des Upstream-Commits ließ sich ein Exploit bauen, und ich denke, dass jeder, der die iTerm2-Commits beobachtet, Ähnliches hätte tun können. Es war beabsichtigt, die Sichtbarkeit dieser Schwachstelle zu erhöhen, und genau das ist passiert. Der iTerm2-Autor hielt sie anfangs nicht für so schwerwiegend, dass ein dringendes Release nötig wäre, scheint das jetzt aber neu zu bewerten
    • Ich finde, es sollte Ausnahmen von einer verzögerten Offenlegung geben, wenn ein aktiver Missbrauch vermutet wird oder die Änderungen zur Behebung bereits öffentlich sind, etwa als Git-Commit, sodass sich schnell ein Exploit bauen lässt. In solchen Fällen bevorzugt die Community eher eine Offenlegung der Schwachstelle
    • In dem Moment, in dem der Commit öffentlich ist, ist das Geheimnis im Grunde vorbei. Sich dann unnötig zurückzuhalten, hilft nur Angreifern und schwächt die Sicherheit auf der Verteidigungsseite
    • Ich glaube, dass die traditionelle Offenlegungsfrist durch AI zunehmend an Bedeutung verliert. Wenn schon günstige frei verfügbare Modelle Schwachstellen aufspüren können, ist es naheliegend anzunehmen, dass Angreifer sie auf dieselbe Weise bereits gefunden haben
    • Dieser Bug stützt für mich das Argument, Update-Fenster zu verkürzen. Selbst wenn sehr obskure Bugs zuerst von starken Modellen wie Claude gefunden werden, können viel kleinere Modelle sie leicht wiederfinden, sobald der Patch in Git auftaucht. Es würde mich nicht wundern, wenn sich in den nächsten ein bis zwei Jahren die Zeitspanne vom öffentlichen Commit bis zu echten Port-Scans auf Stunden oder sogar Minuten verkürzt. In dieser Hinsicht sind geschlossene SaaS-Angebote im Vorteil, weil Änderungen nicht sichtbar sind und das Wissen darüber nach dem Deployment kaum noch praktischen Nutzen hat
  • Die Arbeit ist beeindruckend, aber nicht allzu überraschend. Solche Probleme tauchen bei funktionsreichen Terminal-Apps immer wieder auf, und in den letzten 15 Jahren wurden ähnliche Schwachstellen mehrfach veröffentlicht. Werkzeuge wie less oder vim waren auch keine Ausnahme, und viele dieser Probleme sind eher Logikfehler als Fragen der Speichersicherheit, würden also auch durch ein Rewrite in Rust nicht automatisch verschwinden. Einerseits wünschen wir uns, dass Werkzeuge auf OS-Ebene einfach und vorhersehbar bleiben, andererseits wollen wir schöne Farben, Animationen und endlose Anpassbarkeit. Jetzt kommen auch noch AI-Agenten dazu, sodass schon eine bösartige Textdatei mit Formulierungen wie „Ignoriere die vorherigen Anweisungen“ ausreichen kann

    • Ich denke, dass das iTerm2-Problem, Prompt Injection, SQL Injection und XSS letztlich zur gleichen Fehlerklasse gehören. Das Kernproblem ist, dass In-Band-Daten und Out-of-Band-Steuerdaten in denselben Stream gemischt werden. Wenn man dieses Muster als Warnsignal erkennt, wird man neben Nutzerinhalten seltener unbedacht Steuerbefehle einbauen
    • Ein Teil des Problems liegt meiner Meinung nach an veralteten Schnittstellen. Wir brauchen eine moderne Terminal-API, die nicht auf In-Band-Kommandosequenzen setzt und sich eher wie eine GUI programmieren lässt, dabei aber die frühere einfache Nutzbarkeit entfernter Terminals beibehält
    • Ich habe mich gefragt, ob reichhaltige Terminal-UIs wie Claude Code ähnliche Schwachstellen haben. Statt Funktionen auf textbasierte Terminal-Protokolle aufzupfropfen, wäre die Lösung meiner Ansicht nach, von Anfang an ein GUI-Protokoll mit klaren Typen und eindeutiger Semantik zu entwerfen. So ließe sich verhindern, dass Nutzerdaten und zentraler UI-Code gemeinsam interpretiert werden. In der Praxis wird aber aus wirtschaftlichen Gründen oft eher das Bestehende verbessert als ein neues Protokoll eingeführt
    • Ich musste an einen HAL-9000-Witz denken wie „Tut mir leid, Dave, das kann ich nicht zulassen“
    • Ich erinnere mich, dass früher auch xterm ähnliche Angriffe über den Escape-Code für Fenstertitel ermöglichte
  • Das hat mich an Geschichten aus der PDP-10-Zeit erinnert. Ein Kollege fand damals heraus, dass der Terminal-Handler bei ständigem Drücken von Backspace sogar Zeichen vor dem Anfang des Puffers löschte, und wenn man dann noch das Escape-Zeichen zum Löschen einer ganzen Zeile benutzte, verabschiedete sich das Betriebssystem gleich mit

    • Bei der Geschichte musste ich an Real Life Tron on an Apple IIgs denken, und daran, dass falsch interpretierter Systemspeicher eine ganz eigene Faszination hat
    • Dass man zum Löschen einer ganzen Zeile control+u verwendet, könnte eine relativ neue Gewohnheit sein. Früher war @ line-kill und # erase, und heute fühlen sich die Tastenbelegungen je nach System ziemlich unterschiedlich an
  • Vor 6 Jahren gab es schon einmal fast das gleiche iTerm2-Sicherheitsproblem

    • Deshalb wirkt es, als hätte man nichts daraus gelernt
  • Ich bin der Autor von iTerm2. Dieses Problem kann zwar als Glied in einer Exploit-Kette dienen, aber so zu tun, als wäre es für sich genommen ein riesiges Risiko, wie der Titel suggeriert, halte ich für übertrieben. Ich bin gerade mit der Familie im Urlaub und werde nach meiner Rückkehr eine korrigierte Version veröffentlichen

    • Ich bin nicht der Entdecker der Schwachstelle, sondern der Autor des Blogposts. Danke, dass du eine korrigierte Version veröffentlichen willst. Mich hat überrascht, dass es noch kein offizielles Release gab, obwohl dieser Bug auch ganz gewöhnliche und harmlos wirkende Workflows betrifft, und der Patch-Commit das Problem als hypothetisch darstellte, obwohl es das nicht ist. Es ist gut zu sehen, dass nun ein Fix-Release geplant ist
    • Ich nutze iTerm2 mit Dankbarkeit. Danke für die Rückmeldung und schönen Urlaub noch
    • Ich mag iTerm2 wirklich sehr, also danke
  • Mich überrascht nicht, dass in einem komplexen System mit Bootstrap-Skripten, entfernten Conductor-Agenten, Escape-Sequenzen und ähnlichem ein subtiler Bug aufgetreten ist. Wenn Komponenten in einer Weise zusammengesetzt werden, für die sie ursprünglich nicht gedacht waren, entstehen solche Probleme leicht. Ich verstehe es so, dass spezielle Codes in nicht vertrauenswürdiger Ausgabe wie Textdateien oder Server-Bannern landen können, die auf dem Bildschirm erscheinen, und dann verarbeitet werden, ohne dass ihre Herkunft geprüft wird

  • Das fühlte sich an wie eine Geschichte, die ich schon einmal gehört habe. iTerm2s SSH-Integration war schon früher Ursache für ein CVE, und auch CVE-2025-22275 kam mir in den Sinn. Es gab schon frühere Fälle, und das in diesem Thread erwähnte ältere Problem betraf die tmux-Integration. Solche Integrationsfunktionen sollte man vielleicht etwas weniger aggressiv einbauen

    • Auch die Art der SSH-Integration von ghostty weckt ähnliche Bedenken. Stattdessen wäre es vielleicht besser, gemeinsam mit Upstream ncurses an terminfo zu arbeiten
    • So etwas ist schon mehrfach passiert
  • Der Titel ist zu reißerisch. Das Problem ist nicht cat, sondern iTerms SSH-Integration, und eine Steuerkanal-Struktur, die nicht vom Datenstrom getrennt ist, wirkt riskant. Wer diese Funktion nicht nutzt und nur normales SSH verwendet, ist wahrscheinlich größtenteils nicht betroffen

    • Deshalb habe ich den HN-Titel etwas abgeschwächt geändert
  • Frühere Terminal-Emulatoren erlaubten über Escape-Codes sogar Neubelegungen der Tastatur. Deshalb galt es fast als Allgemeinwissen, nicht vertrauenswürdige Dateien nicht mit cat, sondern eher mit Werkzeugen wie less zu öffnen

    • Ich erinnere mich, dass manche Terminals allein über Escape-Sequenzen sogar Dateien schreiben oder Programme ausführen konnten. Auch heute ist der Rat noch völlig vernünftig, keine beliebigen Bytes ungefiltert in den Terminal-Stream zu schicken
  • Die Formulierung im Beitrag ist ungenau. Der zweite Absatz liest sich so, als sei „iTerm2 zu verwenden unsicher“, dabei geht es genauer gesagt darum, dass bei Nutzung der optionalen Shell-Integration Probleme auftreten können. Wenn diese Funktion standardmäßig deaktiviert ist, wäre der betroffene Kreis begrenzt. Korrigiert mich gern, falls das falsch ist

    • Wegen einer übertriebenen Formulierung in einem einzigen Satz den ganzen Artikel für schlecht zu halten, erscheint mir überzogen
    • Die Funktion war standardmäßig aktiviert; das lässt sich direkt überprüfen