2 pontos por GN⁺ 11 일 전 | 1 comentários | Compartilhar no WhatsApp
  • A integração SSH usa sequências de escape do terminal para se comunicar com o shell remoto, e por causa dessa estrutura até a saída comum do terminal pode ser interpretada como o protocolo do conductor
  • O problema central é uma falha de confiança: arquivos maliciosos, banners, MOTD e respostas do servidor que não são o conductor remoto real também podem agir como se fossem o conductor por meio de DCS 2000p e OSC 135 forjados
  • Apenas ao executar cat readme.txt, se um transcript falso do conductor for renderizado, o iTerm2 prossegue sozinho com o fluxo de getshell·pythonversion·run(...), e a saída atacante só precisa fingir as respostas
  • O exploit explora a confusão em que comandos base64 gravados no PTY acabam caindo como entrada em texto puro no shell local quando não existe um conductor SSH real, e podem ser executados quando o último chunk é interpretado como o caminho ace/c+aliFIo
  • A correção foi aplicada no commit de 31 de março a9e745993c2e2cbb30b884a16617cd5495899f86, mas no momento da divulgação ainda não estava incluída na release stable, criando uma janela de exposição antes da distribuição do patch

Contexto da integração SSH do iTerm2

  • A integração SSH do iTerm2 é um recurso para entender melhor sessões remotas, funcionando com um pequeno script auxiliar chamado conductor enviado ao shell remoto
    • Início da integração SSH via it2ssh
    • Envio do conductor, um script remoto de bootstrap, através da sessão SSH existente
    • Esse script remoto assume o papel de par do protocolo do iTerm2
  • O iTerm2 e o conductor remoto não se comunicam como um serviço de rede comum, mas trocando sequências de escape sobre a E/S do terminal
    • detecção do shell de login
    • verificação da presença de Python
    • mudança de diretório
    • upload de arquivo
    • execução de comandos

Como o PTY funciona

  • Emuladores de terminal modernos são versões em software dos antigos terminais de hardware e são responsáveis por exibir a tela, receber o teclado e interpretar sequências de controle do terminal
  • Como shells e programas de linha de comando ainda esperam um dispositivo que se pareça com um terminal real, o sistema operacional fornece um PTY
    • O PTY é um pseudoterminal que fica entre o emulador de terminal e o processo em primeiro plano
  • Em uma sessão SSH comum, o iTerm2 grava bytes no PTY, o processo em primeiro plano ssh os encaminha para a máquina remota, e o conductor remoto os lê pela stdin
  • Quando o iTerm2 envia comandos ao conductor remoto, localmente isso acaba sendo apenas gravar bytes no PTY

Protocolo do conductor

  • O meio de transporte do protocolo de integração SSH usa sequências de escape do terminal
  • Há dois elementos centrais
    • DCS 2000p serve para fazer hook do conductor SSH
    • OSC 135 serve para mensagens do conductor pre-framer
  • No nível do código-fonte, DCS 2000p faz o iTerm2 criar um parser do conductor, e depois esse parser processa mensagens OSC 135
    • begin <id>
    • linhas de saída do comando
    • end <id> <status> r
    • unhook
  • Um conductor remoto legítimo consegue se comunicar com o iTerm2 apenas pela saída do terminal

Vulnerabilidade central

  • A essência da vulnerabilidade é uma falha de confiança: o iTerm2 aceita como protocolo do conductor SSH até saídas do terminal que não pertencem a uma sessão de conductor realmente confiável
  • Como resultado, saídas de terminal não confiáveis podem se passar por um conductor remoto
    • arquivos maliciosos
    • respostas do servidor
    • banners
    • MOTD
  • A entrada maliciosa pode emitir um hook DCS 2000p forjado e respostas OSC 135 forjadas; nesse caso, o iTerm2 age como se uma troca legítima da integração SSH estivesse em andamento

Como o exploit funciona

  • O arquivo de exploit contém um transcript falso do conductor
  • Quando o usuário executa cat readme.txt, o iTerm2 renderiza o arquivo, mas ele não contém só texto simples; inclui os seguintes elementos
    • uma linha falsa de DCS 2000p que anuncia uma sessão falsa do conductor
    • mensagens falsas de OSC 135 que respondem às requisições do iTerm2
  • Quando o hook é aceito, o iTerm2 inicia o workflow normal do conductor; no código upstream, Conductor.start() envia imediatamente getshell() e, se houver sucesso, depois envia pythonversion()
  • O ataque não precisa injetar essas requisições, porque o próprio iTerm2 as emite, e a saída maliciosa só precisa fingir as respostas

Processo da máquina de estados

  • As mensagens falsas de OSC 135 são mínimas, mas montadas na ordem correta
    • início do body do comando para getshell
    • retorno de uma linha que parece saída de detecção de shell
    • término bem-sucedido desse comando
    • início do body do comando para pythonversion
    • término com falha desse comando
    • unhook
  • Só esse fluxo já faz o iTerm2 entrar no caminho normal de fallback e então concluir que o workflow da integração SSH avançou o suficiente para seguir para a próxima etapa
  • A etapa seguinte é montar e enviar o comando run(...)

O papel de sshargs

  • O hook DCS 2000p forjado inclui vários campos, entre eles sshargs, controlado pelo atacante
  • Esse valor é usado depois como matéria-prima do comando quando o iTerm2 monta a requisição run ... do conductor
  • O exploit escolhe sshargs de forma que, ao o iTerm2 codificar em base64 os dados a seguir,
    • run <padding><magic-bytes>
  • o último chunk de 128 bytes se torne ace/c+aliFIo
  • Essa string não foi escolhida ao acaso; ela foi selecionada para satisfazer simultaneamente duas condições
    • ser uma saída válida do caminho de codificação do conductor
    • ser um nome de caminho relativo válido

A confusão de PTY que torna o exploit possível

  • Em uma sessão legítima de integração SSH, o iTerm2 grava no PTY comandos do conductor codificados em base64, e o ssh os entrega ao conductor remoto
  • Na situação do exploit, o iTerm2 grava os mesmos comandos no PTY, mas como não existe um conductor SSH real, quem os recebe é o shell local como entrada em texto puro
  • Na sessão gravada, observa-se algo como
    • getshell aparecendo em formato base64
    • pythonversion aparecendo em formato base64
    • em seguida, um longo payload run ... codificado em base64
    • o último chunk sendo ace/c+aliFIo
  • Os chunks anteriores falham como comandos sem sentido, e o último funciona se esse caminho existir localmente e puder ser executado

Procedimento de reprodução

  • O PoC original baseado em arquivo pode ser reproduzido com genpoc.py
    • python3 genpoc.py
    • unzip poc.zip
    • cat readme.txt
  • Esse procedimento gera os dois arquivos a seguir
    • um script auxiliar executável chamado ace/c+aliFIo
    • um readme.txt com sequências maliciosas DCS 2000p e OSC 135
  • O primeiro arquivo induz o iTerm2 a se comunicar com o falso conductor, e o segundo fornece o alvo que o shell realmente executará quando o último chunk chegar
  • Para o exploit funcionar, cat readme.txt precisa ser executado no diretório onde existe ace/c+aliFIo, para que o último chunk moldado pelo atacante seja interpretado como um caminho realmente executável

Cronograma de divulgação e patch

  • Bug reportado ao iTerm2 em 30 de março
  • Correção concluída em 31 de março no commit a9e745993c2e2cbb30b884a16617cd5495899f86
  • No momento da escrita, a correção ainda não havia sido incluída na release stable
  • Depois que o commit de patch ficou disponível, foi feita uma tentativa de reconstruir o exploit do zero apenas com base no patch
    • o prompt correspondente está em prompts.md
    • o resultado é genpoc2.py
    • que funciona de forma muito semelhante ao genpoc.py

Questionamentos sobre o momento da divulgação

  • A divulgação ocorreu antes de a correção chegar à release stable, abrindo um cenário em que a maioria dos usuários ainda não tinha proteção prática quando a vulnerabilidade se tornou conhecida
  • Esse conflito sobre o timing da divulgação exige uma justificativa clara
  • Duas semanas é pouco tanto para esperar uma distribuição significativa quanto para justificar que uma divulgação precoce seria necessária para forçar resposta
  • Como resultado, formou-se uma janela de divulgação sem proteção efetiva: a vulnerabilidade ficou amplamente conhecida, mas a versão corrigida ainda não estava realisticamente disponível para os usuários que precisavam dela
  • Uma opção melhor teria sido esperar até que a versão corrigida realmente chegasse aos usuários, ou apresentar uma justificativa clara para a exposição antecipada, mas nenhuma das duas condições foi atendida

1 comentários

 
GN⁺ 11 일 전
Comentários no Hacker News
  • Fiquei me perguntando por que divulgar isso agora, se ainda não saiu um patch para a versão estável. Faz só 18 dias que isso foi reportado ao upstream, e o post do blog é muito mais detalhado do que o commit público, então parece aumentar a viabilidade de exploração real. Confirmo que o autor conseguiu criar um exploit usando apenas o commit do upstream com ajuda de LLM, mas ainda assim acho que este texto aumentou ainda mais a visibilidade da falha

    • Eu não sou a pessoa que descobriu a vulnerabilidade, sou o autor do blog. Já dava para criar um exploit só com o commit do upstream, e acho que qualquer um acompanhando os commits do iTerm2 conseguiria fazer algo parecido. A intenção era aumentar a visibilidade dessa falha, e foi exatamente isso que aconteceu. No começo, o autor do iTerm2 não achou que fosse grave o suficiente para exigir um release emergencial, mas agora parece estar reconsiderando
    • Acho que há exceções ao embargo de divulgação quando há suspeita de exploração ativa, ou quando a correção já foi tornada pública, como em um commit do git, permitindo a criação rápida de exploits. Nesses casos, a comunidade tende a preferir a divulgação da vulnerabilidade
    • No momento em que o commit é publicado, penso que o segredo já acabou. Ficar medindo palavras nessa hora só ajuda os atacantes e enfraquece a segurança de quem está se defendendo
    • Acho que o tradicional período de embargo vai perder cada vez mais sentido por causa da IA. Se até modelos abertos e baratos conseguem encontrar vulnerabilidades, o natural é assumir que os atacantes já encontraram do mesmo jeito
    • Sinto que esse bug reforça meu argumento de encurtar a janela de atualização. Bugs muito obscuros podem até ser descobertos primeiro por modelos fortes como Claude, mas no momento em que o patch sobe para o git, até modelos menores conseguem redescobri-los com facilidade. Não me surpreenderia se, nos próximos 1 ou 2 anos, o intervalo entre publicar um commit e começar o port scan real cair para poucas horas, ou até poucos minutos. Nesse aspecto, SaaS fechado leva vantagem, porque as mudanças não ficam visíveis e, depois do deploy, saber delas quase não traz benefício prático
  • Esse trabalho é legal, mas não achei tão surpreendente. É um problema recorrente em aplicativos de terminal cheios de recursos, e falhas parecidas já foram divulgadas várias vezes nos últimos 15 anos. Ferramentas como less e vim também não ficaram imunes, e boa parte desses problemas está mais para bug de lógica do que para segurança de memória, então reescrever em Rust não resolveria automaticamente. Ao mesmo tempo, há uma tensão entre querer ferramentas de nível de SO simples e previsíveis e, por outro lado, desejar cores bonitas, animações e customização infinita. Agora ainda entraram os agentes de IA, então chegamos ao ponto em que um arquivo de texto malicioso pode conter só algo como "ignore as instruções anteriores"

    • Acho que o problema do iTerm2, prompt injection, SQL injection e XSS são todos erros da mesma família. O ponto central é misturar dados in-band com dados de controle out-of-band no mesmo fluxo. Se a gente passar a reconhecer esse padrão como um sinal de risco, talvez pare de enfiar comandos de controle ao lado de conteúdo do usuário sem pensar muito
    • Acho que parte do problema está em interfaces antigas. Precisamos de uma API de terminal moderna que não dependa de sequências de comando in-band, e que siga mais na direção de algo programável como uma GUI, mas preservando a simplicidade de uso de terminais remotos de antigamente
    • Fiquei curioso se UIs de terminal ricas como Claude Code têm vulnerabilidades parecidas. Em vez de forçar recursos em cima de um protocolo de terminal baseado em texto, acho que a solução seria projetar desde o início um protocolo de GUI com tipos e semântica claros. Assim daria para evitar interpretar misturando dados do usuário com código central da UI. Só que, na prática, por viabilidade econômica, muitas vezes escolhe-se melhorar o que já existe em vez de adotar um protocolo novo
    • Lembrei da piada com o HAL 9000: "Desculpe, Dave, receio não poder permitir isso"
    • Lembro que antigamente o xterm também permitia um ataque parecido abusando do escape code de título da janela
  • Isso me lembrou histórias da era do PDP-10. Um colega descobriu que, se você ficasse pressionando backspace, o handler do terminal acabava apagando caracteres antes do início do buffer e, indo além, se usasse um caractere de escape que limpava a linha inteira, o sistema operacional travava de vez

    • Essa história me fez lembrar de Real Life Tron on an Apple IIgs, e sinto que existe um certo charme estranho que só aparece quando a memória do sistema é interpretada do jeito errado
    • Usar control+u para apagar a linha inteira talvez seja um hábito relativamente recente. Antigamente, @ era line-kill e # era erase, e hoje em dia o comportamento das teclas ainda parece variar bastante de sistema para sistema
  • Quase o mesmo problema de segurança no iTerm2 já tinha acontecido 6 anos atrás

    • Então parece que não aprenderam nada
  • Eu sou o autor do iTerm2. Esse problema pode ser usado como um elo em uma cadeia de exploit, mas dizer, como no título, que sozinho ele representa um risco enorme é exagero. Estou viajando com a família agora e, quando voltar, pretendo lançar uma versão corrigida

    • Eu não sou o descobridor da vulnerabilidade, sou o autor do blog. Obrigado por topar lançar uma correção. Fiquei surpreso por esse bug afetar fluxos de trabalho comuns e aparentemente inofensivos sem que houvesse um release oficial, e o commit do patch tratava o problema como algo hipotético, então quis mostrar que não era. Fico feliz em saber que haverá uma correção
    • Uso o iTerm2 com gratidão. Obrigado por responder, e aproveite as férias
    • Gosto muito do iTerm2, então obrigado
  • Não achei surpreendente que tenha surgido um bug sutil em um sistema complexo que usa script de bootstrap, agente conductor remoto, escape sequence e afins. Quando se usam componentes de um jeito diferente do planejado originalmente, esse tipo de problema aparece com facilidade. Entendo que a estrutura processa sem validar a origem uma saída não confiável exibida na tela, como arquivos de texto ou banners de servidor, quando ela contém códigos especiais

  • Isso pareceu uma história já conhecida. A integração SSH do iTerm2 já foi causa de CVE antes, e também lembrei de CVE-2025-22275. Já houve casos anteriores, e o problema mais antigo citado nesta thread era da integração com tmux. Talvez fosse melhor colocar esse tipo de recurso de integração de forma menos agressiva

    • Tenho preocupações parecidas com a integração SSH do ghostty. Acho que seria melhor colaborar com o ncurses upstream para melhorar o terminfo
    • Isso já se repetiu várias vezes
  • O título está apelativo demais. O problema não é o cat, e sim a integração SSH do iTerm, e essa estrutura de canal de controle não separado do fluxo de dados parece arriscada. Se você não usar esse recurso e ficar no SSH normal, em geral deve estar tudo bem

    • Por isso editei o título no HN para uma formulação um pouco mais branda
  • Emuladores de terminal antigos permitiam até rebinding de teclado por escape code. Por isso, era quase senso comum não dar cat em arquivos não confiáveis e abrir com ferramentas como less

    • Lembro que alguns terminais permitiam até escrever arquivos ou executar programas só com escape sequence. Mesmo hoje, ainda me parece um conselho perfeitamente razoável não despejar bytes arbitrários diretamente no fluxo do terminal
  • O texto está formulado de forma imprecisa. O segundo parágrafo soa como se "usar iTerm2 não fosse seguro", mas o correto seria dizer que pode haver problema ao usar o recurso opcional de Shell Integration. Se esse recurso vem desativado por padrão, entendo que o impacto é limitado. Se eu estiver errado, gostaria de ser corrigido

    • Acho exagerado chamar o texto inteiro de péssimo por causa do exagero de uma frase
    • Esse recurso vinha ativado por padrão, e isso é fácil de verificar