Se você usa iTerm2, até `cat readme.txt` não é seguro
(blog.calif.io)- 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 2000peOSC 135forjados - Apenas ao executar
cat readme.txt, se um transcript falso do conductor for renderizado, o iTerm2 prossegue sozinho com o fluxo degetshell·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
- Início da integração SSH via
- 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
sshos 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 2000pserve para fazer hook do conductor SSHOSC 135serve para mensagens do conductor pre-framer
- No nível do código-fonte,
DCS 2000pfaz o iTerm2 criar um parser do conductor, e depois esse parser processa mensagensOSC 135begin <id>- linhas de saída do comando
end <id> <status> runhook
- 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 2000pforjado e respostasOSC 135forjadas; 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 2000pque anuncia uma sessão falsa do conductor - mensagens falsas de
OSC 135que respondem às requisições do iTerm2
- uma linha falsa de
- Quando o hook é aceito, o iTerm2 inicia o workflow normal do conductor; no código upstream,
Conductor.start()envia imediatamentegetshell()e, se houver sucesso, depois enviapythonversion() - 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 135sã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
- início do body do comando para
- 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 2000pforjado inclui vários campos, entre elessshargs, 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
sshargsde 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
sshos 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
getshellaparecendo em formato base64pythonversionaparecendo 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.pypython3 genpoc.pyunzip poc.zipcat readme.txt
- Esse procedimento gera os dois arquivos a seguir
- um script auxiliar executável chamado
ace/c+aliFIo - um
readme.txtcom sequências maliciosasDCS 2000peOSC 135
- um script auxiliar executável chamado
- 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.txtprecisa ser executado no diretório onde existeace/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
- o prompt correspondente está em
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
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
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"
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
Quase o mesmo problema de segurança no iTerm2 já tinha acontecido 6 anos atrás
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
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
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
Emuladores de terminal antigos permitiam até rebinding de teclado por escape code. Por isso, era quase senso comum não dar
catem arquivos não confiáveis e abrir com ferramentas comolessO 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