- 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- undOSC 135-Sequenzen wie conductor verhalten - Schon das Ausführen von
cat readme.txtreicht aus: Wenn ein gefälschtes conductor-Transcript gerendert wird, durchläuft iTerm2 den Ablaufgetshell·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+aliFIointerpretiert wird - Der Fix wurde im Commit vom 31. März
a9e745993c2e2cbb30b884a16617cd5495899f86eingepflegt, 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
- Start der SSH-Integration über
- 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
sshleitet 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 2000pdient zum Hooken des SSH-conductorOSC 135dient für Pre-Framer-conductor-Nachrichten
- Auf Quellcodeebene sorgt
DCS 2000pdafür, dass iTerm2 einen conductor parser erstellt, der anschließendOSC 135-Nachrichten verarbeitetbegin <id>- command output lines
end <id> <status> runhook
- 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älschteOSC 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.txtausfü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
- eine gefälschte
- Wird der Hook akzeptiert, startet iTerm2 den normalen conductor-Workflow; im Upstream-Quellcode sendet
Conductor.start()sofortgetshell()und danach bei Erfolgpythonversion() - 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
- Start des Command-Bodys für
- 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 kontrolliertensshargs - Dieser Wert wird später von iTerm2 als Baustein des Befehls verwendet, wenn die
run ...-Anfrage des conductor zusammengesetzt wird - Der Exploit wählt
sshargsso, dass iTerm2 die folgenden Daten Base64-kodiertrun <padding><magic-bytes>
- und der letzte 128-Byte-Chunk
ace/c+aliFIoergibt - 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
sshleitet 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
getshellerscheint in Base64-Formpythonversionerscheint 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.pyreproduzierenpython3 genpoc.pyunzip poc.zipcat readme.txt
- Dadurch werden zwei Dateien erzeugt
- ein ausführbares Hilfsskript namens
ace/c+aliFIo readme.txtmit den bösartigen SequenzenDCS 2000pundOSC 135
- ein ausführbares Hilfsskript namens
- 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.txtin dem Verzeichnis ausgeführt werden, in dem sichace/c+aliFIobefindet, 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
a9e745993c2e2cbb30b884a16617cd5495899f86abgeschlossen - 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
- die Prompts dazu in
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
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
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
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
Vor 6 Jahren gab es schon einmal fast das gleiche iTerm2-Sicherheitsproblem
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
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
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 betroffenFrü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 wielesszu öffnenDie 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