2 puntos por GN⁺ 11 일 전 | 1 comentarios | Compartir por WhatsApp
  • La integración SSH usa secuencias de escape de terminal para comunicarse con el shell remoto, y por esa estructura incluso la salida normal del terminal puede interpretarse como el protocolo de conductor
  • El problema central es una falla de confianza: archivos maliciosos, banners, MOTD y respuestas del servidor que no provienen del conductor remoto real también pueden actuar como si fueran conductor mediante DCS 2000p y OSC 135 falsificados
  • Con solo ejecutar cat readme.txt, si se renderiza una transcripción falsa de conductor, iTerm2 avanza por sí solo por el flujo de getshell, pythonversion y run(...), y la salida del ataque solo necesita fingir las respuestas
  • El exploit aprovecha la confusión de que los comandos en base64 escritos al PTY, cuando no existe un conductor SSH real, terminan cayendo como entrada en texto plano del shell local; la ejecución es posible cuando el último chunk se interpreta como la ruta ace/c+aliFIo
  • La corrección se aplicó en el commit del 31 de marzo a9e745993c2e2cbb30b884a16617cd5495899f86, pero al momento de hacerse público todavía no estaba incluida en una versión estable, lo que dejó una ventana de exposición antes de que el parche se distribuyera

Contexto de la integración SSH de iTerm2

  • La integración SSH de iTerm2 es una función para comprender mejor las sesiones remotas, y funciona subiendo al shell remoto un pequeño script auxiliar llamado conductor
    • Se inicia la integración SSH mediante it2ssh
    • Se envía conductor, un script de bootstrap remoto, a través de la sesión SSH existente
    • Ese script remoto actúa como la contraparte del protocolo de iTerm2
  • iTerm2 y el conductor remoto no se comunican como un servicio de red convencional, sino intercambiando secuencias de escape sobre la E/S del terminal
    • detección del shell de inicio de sesión
    • verificación de la presencia de Python
    • cambio de directorio
    • subida de archivos
    • ejecución de comandos

Cómo funciona el PTY

  • Los emuladores de terminal modernos son versiones en software de los antiguos terminales físicos y se encargan de la salida en pantalla, la entrada por teclado y la interpretación de secuencias de control del terminal
  • Como el shell y los programas de línea de comandos siguen esperando un dispositivo que parezca un terminal real, el sistema operativo ofrece un PTY
    • Un PTY es un pseudoterminal ubicado entre el emulador de terminal y el proceso en primer plano
  • En una sesión SSH típica, iTerm2 escribe bytes al PTY, el proceso en primer plano, ssh, los reenvía a la máquina remota, y el conductor remoto los lee por stdin
  • Cuando iTerm2 envía comandos al conductor remoto, en lo local finalmente lo hace escribiendo bytes al PTY

Protocolo de conductor

  • El medio de transporte del protocolo de integración SSH usa secuencias de escape de terminal
  • Hay dos elementos clave
    • DCS 2000p se usa para enganchar al conductor SSH
    • OSC 135 se usa para los mensajes de conductor previos al framing
  • A nivel de código, DCS 2000p hace que iTerm2 cree un parser de conductor, y luego ese parser procesa mensajes OSC 135
    • begin <id>
    • líneas de salida del comando
    • end <id> <status> r
    • unhook
  • Un conductor remoto legítimo puede comunicarse con iTerm2 solo mediante la salida del terminal

Vulnerabilidad principal

  • La esencia de la vulnerabilidad es una falla de confianza: iTerm2 acepta como protocolo del conductor SSH incluso salidas de terminal que no pertenecen a una sesión de conductor confiable real
  • Como resultado, una salida de terminal no confiable puede hacerse pasar por el conductor remoto
    • archivos maliciosos
    • respuestas del servidor
    • banners
    • MOTD
  • La entrada del ataque puede emitir un hook DCS 2000p falsificado y respuestas OSC 135 también falsificadas; en ese caso, iTerm2 actúa como si realmente estuviera en curso un intercambio de integración SSH

Cómo funciona el exploit

  • El archivo de exploit contiene una transcripción falsa de conductor
  • Cuando el usuario ejecuta cat readme.txt, iTerm2 renderiza el archivo, pero este no contiene solo texto: incluye los siguientes elementos
    • una línea falsa de DCS 2000p que anuncia una sesión falsa de conductor
    • mensajes falsos de OSC 135 que responden a las solicitudes de iTerm2
  • Si el hook es aceptado, iTerm2 inicia el flujo normal de conductor, y en el código fuente Conductor.start() envía de inmediato getshell() y, si tiene éxito, luego envía pythonversion()
  • El ataque no necesita inyectar esas solicitudes: iTerm2 las emite por sí mismo, y la salida maliciosa solo debe fingir las respuestas

Progresión de la máquina de estados

  • Los mensajes falsos de OSC 135 son mínimos, pero están construidos en el orden exacto
    • inicio del cuerpo del comando para getshell
    • devolución de una línea que parece salida de detección del shell
    • fin exitoso de ese comando
    • inicio del cuerpo del comando para pythonversion
    • fin fallido de ese comando
    • unhook
  • Solo con ese flujo, iTerm2 entra en una ruta normal de fallback y luego decide que el flujo de integración SSH se completó lo suficiente como para pasar al siguiente paso
  • El siguiente paso es construir y enviar el comando run(...)

El papel de sshargs

  • El hook DCS 2000p falsificado incluye varios campos, entre ellos sshargs, controlado por el atacante
  • Ese valor se usa después como material de comando cuando iTerm2 construye la solicitud run ... del conductor
  • El exploit elige sshargs para que, cuando iTerm2 codifique en base64 los siguientes datos,
    • run <padding><magic-bytes>
  • el último chunk de 128 bytes se convierta en ace/c+aliFIo
  • Esta cadena no se eligió al azar, sino para satisfacer simultáneamente estas dos condiciones
    • ser una salida válida de la ruta de codificación del conductor
    • ser un nombre de ruta relativa válido

La confusión del PTY que hace posible el exploit

  • En una sesión normal de integración SSH, iTerm2 escribe al PTY comandos del conductor codificados en base64, y ssh los reenvía al conductor remoto
  • En la situación del exploit, iTerm2 escribe esos mismos comandos en el PTY, pero como no existe un conductor SSH real, el shell local los recibe como entrada en texto plano
  • En la sesión grabada se observa una forma como esta
    • getshell aparece en base64
    • pythonversion aparece en base64
    • luego aparece un payload largo run ... codificado en base64
    • el último chunk es ace/c+aliFIo
  • Los chunks anteriores fallan como comandos sin sentido, pero el último funciona si esa ruta existe en local y es ejecutable

Procedimiento de reproducción

  • El PoC original basado en archivos puede reproducirse con genpoc.py
    • python3 genpoc.py
    • unzip poc.zip
    • cat readme.txt
  • Este procedimiento crea los siguientes dos archivos
    • un script auxiliar ejecutable llamado ace/c+aliFIo
    • readme.txt, que contiene secuencias maliciosas DCS 2000p y OSC 135
  • El primer archivo induce a iTerm2 a comunicarse con el conductor falso, y el segundo proporciona el objetivo que el shell realmente ejecutará cuando llegue el último chunk
  • Para que el exploit tenga éxito, cat readme.txt debe ejecutarse desde el directorio que contiene ace/c+aliFIo, de modo que el último chunk configurado por el atacante se interprete como una ruta ejecutable real

Cronograma de divulgación y parche

  • El 30 de marzo se reportó el bug a iTerm2
  • El 31 de marzo se completó la corrección en el commit a9e745993c2e2cbb30b884a16617cd5495899f86
  • Al momento de redactarse, la corrección todavía no estaba incluida en una versión estable
  • Después de aplicarse el commit del parche, se intentó reconstruir el exploit desde cero basándose únicamente en el parche
    • los prompts de ese proceso están en prompts.md
    • el resultado es genpoc2.py
    • funciona de forma muy similar a genpoc.py

Cuestionamientos sobre el momento de la divulgación

  • La divulgación ocurrió antes de que la corrección llegara a una versión estable, abriendo una ventana en la que a la mayoría de los usuarios les resultaba difícil estar realmente protegidos pese a que la vulnerabilidad ya era conocida
  • Ese conflicto sobre el momento de divulgar exige una justificación clara
  • Dos semanas es poco tiempo tanto para esperar una distribución significativa del parche como para justificar que era necesario forzar una respuesta mediante una divulgación temprana
  • Como resultado, la vulnerabilidad pasó a ser ampliamente conocida, pero la versión corregida todavía no estaba disponible en la práctica para los usuarios que la necesitaban, creando una ventana de exposición pública
  • Una mejor opción habría sido esperar a que la versión corregida llegara realmente a manos de los usuarios o presentar un fundamento claro de por qué era necesario exponerlo antes, pero no se cumplió ninguna de las dos

1 comentarios

 
GN⁺ 11 일 전
Opiniones de Hacker News
  • Me preguntaba por qué lo hicieron público ahora, cuando todavía no sale un parche para la versión estable. Solo habían pasado 18 días desde que se reportó upstream, y el post del blog era mucho más detallado que el commit público, así que sentí que aumentaba la posibilidad de explotación real. El autor confirmó que pudo crear un exploit usando un LLM solo con el commit upstream, pero aun así creo que este artículo hizo la vulnerabilidad mucho más visible

    • Yo no soy quien descubrió la vulnerabilidad, sino el autor del blog. Se podía construir un exploit solo con el commit upstream, y creo que cualquiera que vigilara los commits de iTerm2 podría haber hecho algo parecido. Sí hubo una intención de aumentar la visibilidad de esta vulnerabilidad, y en efecto eso pasó. Al principio el autor de iTerm2 no pensó que fuera lo bastante grave como para requerir una publicación urgente, pero ahora parece que lo está reconsiderando
    • Creo que hay excepciones al embargo de divulgación cuando se sospecha de explotación activa real, o cuando la corrección ya está publicada, como en un commit de git, y eso permite crear exploits rápidamente. En situaciones así, la comunidad más bien prefiere que se divulgue la vulnerabilidad
    • Pienso que en el momento en que el commit se hace público, el secreto ya se acabó. Guardarse detalles solo ayuda a los atacantes y debilita la seguridad de quienes se defienden
    • Siento que el periodo tradicional de divulgación responsable va a ir perdiendo sentido por culpa de la IA. Si incluso modelos abiertos y baratos pueden encontrar vulnerabilidades, lo natural es asumir que los atacantes ya las encontraron del mismo modo
    • Siento que este bug refuerza mi argumento de acortar la ventana de actualizaciones. Aunque un bug muy complejo lo encuentre primero un modelo potente como Claude, en cuanto el parche sube a git hasta modelos más pequeños pueden redescubrirlo con facilidad. No me sorprendería que en los próximos 1 o 2 años el tiempo entre publicar un commit y un escaneo de puertos real se reduzca a horas, o incluso minutos. En ese sentido, el SaaS cerrado tiene ventaja, porque no se ven los cambios y después del despliegue saberlos suele servir de poco
  • El trabajo está muy bien, pero no me pareció tan sorprendente. Es un problema que aparece una y otra vez en aplicaciones de terminal con muchas funciones, y en los últimos 15 años se han divulgado varias vulnerabilidades parecidas. Herramientas como less o vim tampoco fueron la excepción, y muchos de estos problemas se parecen más a bugs de lógica que a problemas de seguridad de memoria, así que reescribirlo en Rust no los resolvería automáticamente. Por un lado queremos que las herramientas a nivel de SO sean simples y predecibles, pero por otro también queremos colores bonitos, animaciones y personalización infinita. Y ahora además entran los agentes de IA, así que ya vivimos en una época donde un archivo de texto malicioso podría contener nada más una frase como "ignora las instrucciones anteriores"

    • Creo que el problema de iTerm2, la inyección de prompts, SQL injection y XSS son en el fondo la misma clase de error. El problema central es mezclar datos in-band con datos de control out-of-band en el mismo flujo. Si empezamos a reconocer este patrón como una señal de peligro, quizá dejemos de meter comandos de control junto al contenido del usuario sin pensarlo demasiado
    • Creo que parte del problema está en interfaces antiguas. Hace falta una API de terminal moderna que no dependa de secuencias de comandos in-band, y que mantenga la simpleza de uso de los terminales remotos tradicionales, pero con la capacidad de programación de una GUI
    • Me preguntaba si interfaces de terminal ricas como Claude Code tienen vulnerabilidades parecidas. En vez de forzar más funciones sobre un protocolo de terminal basado en texto, creo que la solución sería diseñar desde el inicio un protocolo GUI con tipos y semántica claras. Así se evita interpretar mezclados los datos del usuario y el código central de la UI. Pero en la práctica, por costos, muchas veces se elige mejorar lo existente en lugar de introducir un protocolo nuevo
    • Me vino a la cabeza un chiste de HAL 9000 tipo "Lo siento, Dave, no puedo permitir eso"
    • Recuerdo que antes en xterm también era posible hacer ataques parecidos abusando del código de escape del título de ventana
  • Me acordé de la época del PDP-10. Un colega descubrió que, si seguía presionando backspace, el manejador del terminal borraba incluso caracteres anteriores al inicio del buffer; y luego, si usabas un carácter de escape para borrar toda una línea, terminabas tumbando el sistema operativo

    • Esta historia me recordó a Real Life Tron on an Apple IIgs, y siento que hay cierto encanto extraño en esos casos donde la memoria del sistema se interpreta mal
    • Puede que usar control+u para line-kill sea una costumbre relativamente reciente. Antes @ era line-kill y # era erase, y hoy en día la forma en que responden esas teclas se siente bastante distinta según el sistema
  • Hace 6 años ya hubo casi el mismo problema de seguridad en iTerm2

    • Así que parece que no aprendieron nada
  • Soy el autor de iTerm2. Creo que esto puede servir como un eslabón dentro de una cadena de explotación, pero presentarlo como si por sí solo fuera un riesgo enorme, como sugiere el título, me parece una exageración. Ahora mismo estoy de viaje con mi familia y cuando regrese voy a publicar una versión corregida

    • Yo no soy quien descubrió la vulnerabilidad, sino el autor del blog. Gracias por comprometerte a sacar una corrección. Me sorprendió que no hubiera una versión oficial, dado que este bug afecta incluso flujos de trabajo comunes y aparentemente inocuos, y quise mostrar que no era algo hipotético, como sugería el commit del parche. Me alegra que sí vayan a sacar una corrección
    • Uso iTerm2 con agradecimiento. Gracias por responder y que disfrutes tus vacaciones
    • Me encanta iTerm2, gracias
  • No me sorprendió que apareciera un bug sutil en un sistema complejo que usa scripts de bootstrap, agentes conductor remotos, secuencias de escape y demás. Cuando se ensamblan componentes de una forma para la que no fueron diseñados, este tipo de cosas pasa fácilmente. Entiendo que si una salida no confiable que se muestra en pantalla, como un archivo de texto o el banner de un servidor, contiene códigos especiales, la arquitectura puede terminar procesándolos sin validar su origen

  • Sentí que esta historia ya la había visto antes. Hubo un caso donde la integración SSH de iTerm2 fue la causa de un CVE, y también me vino a la mente CVE-2025-22275. Ya había antecedentes, y el problema viejo que se mencionó en este hilo era del lado de la integración con tmux. Tal vez convendría meter estas funciones de integración de forma un poco menos agresiva

    • El enfoque de integración SSH de ghostty también me genera preocupaciones parecidas. Preferiría que colaboraran con upstream ncurses para mejorar terminfo
    • Esto ya ha pasado varias veces
  • El título es demasiado sensacionalista. El problema no es cat, sino la integración SSH de iTerm, y una arquitectura de canal de control que no está separada del flujo de datos parece riesgosa. Si no usas esa función y solo usas SSH normal, en general deberías estar bien

    • Por eso ajusté el título en HN a una redacción un poco más suave
  • Antes algunos emuladores de terminal permitían incluso reconfigurar teclas del teclado mediante códigos de escape. Por eso era casi sentido común no hacer cat a archivos no confiables, sino abrirlos con herramientas como less

    • Recuerdo que algunos terminales podían incluso escribir archivos o ejecutar programas solo con secuencias de escape. Aun hoy, sigue siendo un consejo perfectamente razonable no pasar bytes arbitrarios tal cual al flujo del terminal
  • La redacción del artículo es imprecisa. El segundo párrafo suena como si "usar iTerm2 no fuera seguro", cuando lo más correcto sería decir que puede haber problemas al usar la función opcional de Shell Integration. Si esa función viene desactivada por defecto, entiendo que el alcance sería limitado. Si estoy equivocado, agradecería una corrección

    • Me parece exagerado decir que todo el artículo es malísimo por una sola frase exagerada
    • Esa función venía activada por defecto y se puede comprobar directamente