← Voltar para todas as publicações
Publicado em · por Renaud Deraison

O stealer levou os substitutos

Em 15 de outubro, a Symantec relatou que o Aoki, um infostealer visto pela primeira vez este ano, agora vai atrás das credenciais de agentes de código: .claude.json, o config.toml e os arquivos .env do Codex, tokens do GitHub Copilot, Cursor, Gemini, JetBrains AI Assistant e Kiro, e chaves da AWS. No Bromure Agentic Coding, cada um desses arquivos guarda um substituto, os logins e as chaves ficam criptografados no Mac, e um substituto enviado ao servidor de um stealer pausa a máquina.

A lista do stealer agora começa pelo seu agente de código. Ele quer o .claude.json, a config do Codex e os arquivos .env ao lado dela.

Um infostealer costumava ir atrás de cookies do navegador, senhas salvas, carteiras de cripto e tokens do Discord. O Aoki ainda leva tudo isso. As versões recentes também procuram os arquivos que o seu agente de código guarda na sua pasta pessoal.

A Threat Hunter Team da Symantec descreveu a mudança na quarta-feira, 15 de outubro, em Aoki: Infostealer Targets AI Coding Assistant Credentials. A Infosecurity Magazine noticiou no mesmo dia. O Aoki, também chamado de Aokigahara por causa de uma string na sua rotina de descriptografia, apareceu no início deste ano. A Symantec escreve que “as versões anteriores do malware não miravam arquivos relacionados a IA”. A amostra mais nova mira.

O que o Aoki leva

A Symantec lista os arquivos de agente da amostra mais nova:

  • .claude.json e os cookies do Claude desktop.
  • Os cookies do ChatGPT.
  • O config.toml e os arquivos .env do Codex.
  • O banco de estado local do Cursor, que “pode guardar em cache o contexto de conversas e trechos de código”.
  • Tokens do GitHub Copilot, Cursor, Google Gemini, JetBrains AI Assistant e Kiro.
  • Credenciais da AWS.

O resto da lista é o butim de sempre de um infostealer: mais de quarenta navegadores, cerca de noventa extensões de carteira, carteiras desktop, gerenciadores de senhas, Telegram, Discord, clientes FTP e VPN. O Aoki também procura qualquer arquivo cujo nome contenha secret, privatekey, keystore, mnemonic, passphrase ou backup. A Symantec observa que “o malware não tem lista de comandos de backdoor”. Ele coleta o que encontra e envia por POST a um endpoint /gate no seu servidor de comando e controle.

A Symantec explica por que os arquivos de agente valem o esforço: “Assim como dados de cartão, uma chave de IA roubada pode ser convertida em dinheiro diretamente.” O comprador gasta uso na sua conta, prática conhecida como LLMjacking. Os mesmos tokens “podem permitir que atacantes ajam sob a identidade de um usuário legítimo” e alcançam os repositórios, as contas de nuvem e os pipelines de CI/CD conectados à conta.

A Symantec não diz como o Aoki chega a uma máquina. No notebook de um desenvolvedor com um agente de código, a porta de entrada óbvia é um pacote. O agente instala dezenas deles por conta própria todo dia, e uma dependência maliciosa com um script postinstall roda com as permissões do agente assim que o npm install termina.

A mesma lista numa máquina Bromure

No Bromure Agentic Coding, o agente roda numa VM Linux no seu Mac. Credenciais reais nunca entram nessa VM. O Mac as guarda num cofre criptografado e grava substitutos na VM, com o mesmo formato das reais, para que todas as ferramentas os aceitem. Um proxy no Mac troca cada substituto pelo valor real na rede, e só em requisições para o host ao qual a credencial pertence.

Coloque um stealer com a lista do Aoki dentro dessa VM e acompanhe-o item a item.

.claude.json e a chave do Claude

O Claude Code na VM roda com sk-ant-api03-brm-…, uma chave substituta. Se você entrou com uma assinatura do Claude, os tokens OAuth foram capturados no Mac durante o login e armazenados, criptografados, em claude-subscription.enc. O host renova o token de acesso uns cinco minutos antes de ele expirar e o injeta nas requisições destinadas à Anthropic. A VM nunca guarda um refresh token, então nem o .claude.json nem nenhum outro arquivo da pasta pessoal tem uma credencial válida do Claude para o stealer levar.

config.toml, auth.json e .env do Codex

O Codex recebe um ~/.codex/auth.json pré-preenchido com um JWT falso de validade muito distante, para que o cliente não tente renová-lo. O login real do ChatGPT fica no Mac, em codex-subscription.enc. Uma chave de API da OpenAI aparece na VM como sk-brm-….

Um .env de projeto importado com Import env file… no painel Credentials da máquina volta com os mesmos nomes de variáveis, cada valor um substituto brm_… restrito aos hosts que você escolher. Seu código lê STRIPE_KEY como sempre leu, e o stealer lê brm_….

GitHub, AWS e SSH

~/.git-credentials e GH_TOKEN guardam um substituto ghp_ de 40 caracteres, como o real. Não existe ~/.aws/credentials. O ~/.aws/config aponta para um helper credential_process que entrega ao SDK da AWS o ID real da chave de acesso com uma chave secreta falsa de 40 caracteres, e o Mac assina de novo cada requisição a caminho da AWS. Um stealer que copia a saída do helper leva uma chave secreta que só produz InvalidSignatureException.

A busca por palavra-chave por privatekey ou id_ed25519 não encontra nada. O SSH_AUTH_SOCK na VM é uma ponte para um agente de assinatura no Mac, e os bytes da chave privada nunca a atravessam.

Cookies

O Aoki quer os cookies do Claude desktop e do ChatGPT. A VM da máquina não tem app desktop nem perfil de navegador para ler. Quando você entra no Claude ou no ChatGPT para o Bromure, a página de login abre no navegador do seu Mac e os tokens vão para o cofre. O agente navega com um Chromium que roda na sua própria VM auxiliar descartável, separada da VM da máquina, então um stealer na VM do agente não alcança o perfil do navegador.

A lista de um stealer, dentro de uma máquina BromureVM do agenteArquivo que o stealer abreO que ele encontra~/.claude.json, ANTHROPIC_API_KEYsk-ant-api03-brm-… (substituto)~/.codex/auth.json, config.tomlJWT falso, sk-brm-….env do projetoSTRIPE_KEY=brm_…~/.git-credentials, GH_TOKENghp_… (substituto)credenciais da AWSID de chave real + segredo falso~/.ssh/id_*sem arquivo (ponte de assinatura)O Mac, fora da VMCofre criptografado (AES-GCM)chave mestra no Data ProtectionKeychain, sem sincronizar no iCloudclaude-subscription.enccodex-subscription.encmodels.encsegredos do workspace, chaves SSHOs refresh tokens ficam aqui.O proxy só coloca o valor realpara o host ao qual ele pertence.POST https://dobeqnesmot.cc/gatecorpo: sk-ant-api03-brm-…, ghp_…, brm_…Proxy do Mac: substitutos indo para o host errado451, nada encaminhado, VM pausada
A lista do Aoki, executada dentro de uma máquina Bromure. Todo arquivo da lista existe e guarda um substituto. Quando o stealer envia o butim para /gate, o proxy no Mac encontra substitutos indo para um host para o qual nunca foram emitidos, responde 451 e pausa a VM.

O envio para /gate

O Aoki termina enviando o butim por POST para /gate. A Symantec cita dobeqnesmot[.]cc, hjazfioe[.]surf e neihite[.]cc. Numa máquina Bromure, essa requisição precisa sair pelo proxy no Mac, porque o proxy é a única rota da VM para a rede.

O proxy examina cada requisição de saída, cabeçalhos e corpo, em busca de substitutos indo para qualquer lugar que não seja o host para o qual foram emitidos. Um valor sk-ant-api03-brm-… tem uma única família de destinos legítima, a Anthropic. Um substituto ghp_ pertence ao GitHub. Dentro de um POST para um domínio .cc, eles só podem significar exfiltração. O proxy responde HTTP 451 e não encaminha nada. A VM pausa na hora, e o Mac mostra This environment may have been compromised, com uma linha por substituto vazado: uma prévia do token, o nome da credencial, o host ao qual ela pertence e o host que o stealer tentou.

Você escolhe o que acontece em seguida. Save for Investigation exporta o disco da VM, a pasta pessoal e as pastas compartilhadas para uma pasta que você escolher e depois desliga a máquina. Shut down a desliga e a marca como comprometida. Uma máquina comprometida só volta a iniciar depois de Wipe and Launch, que substitui o disco e a pasta pessoal e mantém seus tokens, chaves SSH e configurações. Seu login do Claude, seu token do GitHub e suas chaves da AWS nunca estiveram na VM, então o stealer não copiou nada que precise ser trocado.

Você também pode barrar o envio antes da verificação. No painel Guardrails da máquina, defina Unmatched traffic como Deny em Outbound connections e liste os hosts de que a máquina precisa. Uma conexão a um domínio .cc desconhecido passa então a ser recusada, e a Security Timeline mostra uma linha vermelha Firewall para ela.

Se o stealer empacotar o butim de modo que a verificação não consiga ler os substitutos, o servidor do outro lado ainda recebe valores que não autenticam em lugar nenhum. Um substituto só funciona quando passa pelo proxy do seu Mac a caminho do host para o qual foi emitido.

Antes de o stealer rodar

O caminho mais provável para dentro da VM de um agente é um pacote que o agente instalou. O painel Supply Chain da máquina verifica cada download no Mac antes que a VM o veja:

  • A carência de idade, ativada por padrão com um mínimo de dois dias, esconde versões de pacotes mais novas que o limite. Uma versão sequestrada que é retirada em poucas horas nunca chega ao npm install.
  • A remoção de scripts de instalação, quando você a ativa, tira os hooks preinstall, install, postinstall e prepare de cada tarball npm em trânsito, o jeito habitual de um malware npm rodar na instalação.
  • OSV, socket.dev ou Depi bloqueiam versões com alertas de segurança conhecidos e pacotes marcados como malware ou typosquats, com um 451 cujo motivo o gerenciador de pacotes imprime literalmente.

Todo download aparece na Security Timeline, então depois de um incidente você encontra o pacote que trouxe o stealer.

Se o stealer rodar no Mac

A lista de arquivos do Aoki também diz o que um stealer encontra no próprio Mac, e uma instalação do Bromure não acrescenta nada a ela. O Bromure não importa os logins das CLIs do Claude ou do Codex do seu Mac e não precisa deles: os agentes rodam na VM, e os logins deles ficam no cofre. Tudo sob ~/Library/Application Support/BromureAC/ que guarda um segredo é texto cifrado AES-GCM. A chave mestra fica no Data Protection Keychain, restrita à identidade de assinatura do Bromure, e nunca sincroniza. Um stealer que copia a pasta leva blobs criptografados.

A Symantec destaca o banco local do Cursor porque ele guarda em cache o contexto das conversas e o código. O registro do Bromure sobre o que o agente fez, o trace da sessão, é criptografado em repouso com a mesma chave do cofre, e guarda as trocas de tokens só como prévias do primeiro e do último caractere. Nenhum segredo real aparece num trace, criptografado ou não.

Todo arquivo da lista guarda um substituto

.claude.json, o auth.json e o config.toml do Codex, valores .env importados, credenciais do git e a config da AWS carregam substitutos. Refresh tokens e chaves privadas SSH nunca entram na VM.

O envio para a máquina

O proxy encontra substitutos indo para um host para o qual não foram emitidos, responde 451, pausa a VM e nomeia cada credencial vazada.

Nada para trocar

Wipe and Launch substitui o disco e a pasta pessoal e mantém suas chaves. O stealer levou valores que só funcionam pelo proxy do seu Mac.

A porta é vigiada

A carência de idade, a remoção de scripts de instalação e as checagens de reputação rodam no Mac antes de um pacote chegar à VM, e todo download fica registrado.

A lista vai crescer

A Symantec diz que os recursos do Aoki “ainda parecem estar em desenvolvimento ativo”, e outros stealers vão copiar a lista dele. O Aoki incluiu os arquivos de agente porque chaves e logins de agente roubados vendem. Rode seus agentes numa máquina Bromure e o comprador recebe um pacote de substitutos que nenhum servidor fora do proxy do seu Mac aceita.

Para a versão do dia a dia do mesmo problema, em que o próprio agente copia um segredo para a transcrição, leia A transcrição guardou o token. Para um worm que foi atrás dos mesmos arquivos a partir de um pacote npm comprometido, leia Revogar o token era o gatilho.