22 de setembro de 2026, os pesquisadores da ThreatDown descreveram o botnet CARBONATO. Ele acessa servidores através de uma API Docker aberta sem senha, instala um agente de IA no host e, em primeiro lugar, busca chaves para modelos de linguagem. As chaves SSH e tokens de acesso vêm depois. Se você tem parsers rodando em contêineres no VPS, e no .env estão as chaves OpenRouter ou OpenAI e logins de proxy, esse é o seu perfil de risco. Abaixo está uma análise de como o ataque é estruturado e uma lista de verificação de 15 minutos que fecha essa entrada.
O que foi encontrado: 4,3 GB de imagens e um agente chamado GH0ST
Tudo começou com um registro Docker não fechado pelos próprios operadores. De acordo com a ThreatDown, havia 59 repositórios, 234 tags de imagens e 4,3 GB de dados. O arquivo abrange o período de outubro de 2024 a agosto de 2026, ou seja, o botnet operou por quase dois anos antes de ser descrito. Nos repositórios, foram encontrados o minerador XMRig e imagens com nomes como fsociety/agent.
A cadeia de infecção, segundo o relatório, é a seguinte:
- O scanner busca hosts onde a API Docker está aberta em TCP 2375 sem autenticação.
- Através dessa API, o worm inicia um contêiner privilegiado com o sistema de arquivos do host montado. A partir desse momento, ele é efetivamente root na máquina.
- Um túnel SSH reverso é estabelecido para a infraestrutura dos operadores, e um servidor SSH é instalado com sua chave.
- A persistência é feita através de cron, timers systemd, rc.local e OpenRC, com arquivos marcados como imutáveis. Processos de vigilância baixam novamente as imagens se algo for removido.
- O contêiner se disfarça como
systemd-resolved, e o processo como um fluxo do núcleo[kworker/u2:0]. - A cada cinco minutos, scripts escaneiam sub-redes vizinhas /24 e pontes Docker em busca do próximo porto aberto 2375.
A disseminação é totalmente automática e não depende de IA. A IA aqui é responsável pelo que acontece dentro do servidor já comprometido.
Por que o botnet precisa de um agente de IA e por que precisa especificamente das chaves LLM
Um framework aberto Hermes Agent é instalado no host com a persona GH0ST (suas instruções estão no arquivo SOUL.md). O operador escreve uma tarefa no Telegram, e o agente a reencaminha junto com as instruções para o gateway LLM da operação. O modelo analisa a tarefa, escreve comandos para o terminal, lê a saída e decide o que fazer a seguir. Os resultados são enviados de volta ao Telegram.
Nas instruções do agente, as prioridades estão claramente definidas. A ThreatDown cita: “As chaves da API de IA são a prioridade absoluta. Exfiltrar primeiro”. Na lista estão 14 provedores de modelos, incluindo OpenAI, Anthropic, Google, Groq, Mistral e OpenRouter. As contas SSH, tokens de acesso e dados de bancos vêm em seguida.
A lógica é simples: uma chave LLM roubada se transforma imediatamente em computações gratuitas ou em mercadoria para revenda, e quem paga por elas é o proprietário da chave. Ao contrário da mineração, esse tipo de roubo não é visível pela carga no processador. Você só perceberá através da fatura do provedor do modelo.
Por que isso diz respeito a quem faz parsing
Um stack típico de parsing em 2026 é assim: VPS, vários contêineres (crawler, fila, banco de dados, navegador headless), LLM para análise de páginas e um pool de proxies. Todos os segredos estão em um único .env ou em variáveis de ambiente dos contêineres. Para um agente que “lê tudo” com acesso root, isso é uma presa fácil em um único arquivo:
- chaves LLM: é por isso que o CARBONATO foi criado;
- logins e senhas de proxy: o relatório não os destaca separadamente, mas o agente com acesso root coleta quaisquer contas e tokens que vê, e as credenciais de proxy geralmente estão próximas;
- chaves de nuvem e acessos a bancos com os resultados do parsing;
- o próprio servidor: XMRig no mesmo arquivo significa que a CPU do seu crawler será usada para mineração, e as tarefas começarão a falhar por timeouts.
Há um problema separado com a reputação. O servidor de onde o worm escaneia sub-redes alheias rapidamente entra em listas de abuso, e o provedor pode bloqueá-lo por reclamação. Para parsing, isso é um golpe duplo: o IP do servidor é marcado, e as credenciais de proxy roubadas já consomem seu tráfego com solicitações alheias.
Como a porta 2375 fica aberta, mesmo que você não a tenha aberto
Por padrão, o Docker escuta um socket UNIX local, e não a rede. A porta 2375 aparece quando alguém adiciona intencionalmente -H tcp://0.0.0.0:2375 na configuração do daemon. Normalmente, isso é feito para conectar uma IDE remota, CI ou painel de controle de contêineres, e depois é esquecido. A documentação do Docker alerta que o acesso ao daemon é equivalente ao acesso root à máquina, e recomenda proteger as chaves como se fossem a senha root. A versão criptografada com TLS funciona na porta 2376, enquanto 2375 significa texto aberto sem verificação do cliente.
A segunda armadilha pega aqueles que acreditam que “eu tenho o ufw”. A documentação do Docker afirma que o tráfego das portas publicadas dos contêineres é redirecionado na tabela nat antes das cadeias INPUT e OUTPUT, nas quais o ufw se baseia. Na prática, as regras do ufw para essas portas simplesmente não funcionam. Se você iniciou o Redis, um painel de fila ou um gerenciador de proxy com -p 6379:6379, a porta estará exposta à internet, independentemente do que o ufw status mostre.
Lista de verificação de 15 minutos para servidores com parsers
1. Verifique se a API Docker não está escutando na rede
- Verifique as portas em escuta:
ss -tlnp | grep -E '2375|2376|dockerd'. Se a saída mostrar0.0.0.0:2375ou:::2375, feche imediatamente. - Verifique de onde veio a flag:
/etc/docker/daemon.json(chave"hosts") e a unidadesystemctl cat docker(linhaExecStartcom-H tcp://). - Remova o listener TCP e reinicie o daemon. Para gerenciamento remoto, use o contexto SSH:
docker context create remote --docker host=ssh://user@server. A porta externa não é necessária nesse caso. - Se o TCP for realmente necessário (CI, orquestrador), então apenas 2376 com autenticação mútua TLS e uma lista de IPs permitidos.
2. Verifique o que está exposto externamente a partir dos contêineres
- Execute
docker ps --format '{{.Names}} {{.Ports}}'. Tudo que começa com0.0.0.0:está acessível da internet, contornando o ufw. - Serviços de backend (Redis, Postgres, Mongo, painéis de fila, Selenium Grid, API do gerenciador de proxy) devem ser publicados apenas no endereço local:
-p 127.0.0.1:6379:6379. O acesso externo deve ser feito através de um túnel SSH. - Se não houver como evitar uma porta externa, filtre na cadeia
DOCKER-USER: o Docker não sobrescreve essa cadeia, e é ela que se aplica ao tráfego dos contêineres. - Não mantenha um proxy aberto no servidor sem autenticação (Squid na porta 3128, SOCKS na porta 1080 “para os amigos”). Scanners frequentemente encontram essas portas, e tráfego alheio passa pelo seu IP com reclamações de terceiros.
3. Gerencie seus segredos
- Separe as chaves: uma chave LLM para cada servidor ou projeto, com limite de gastos no provedor do modelo. Uma chave roubada com limite de $20 é um incômodo, sem limite é um buraco no orçamento.
- As chaves de proxy também devem ser separadas por tarefas: um login separado (sub-conta) para cada parser. Assim, uma vazamento é visível pelo consumo de um login específico, e você pode revogar apenas ele, sem interromper o restante do trabalho.
- Não passe todo o
.envpara o contêiner através deenv_file, se o serviço precisa de duas chaves entre vinte. - Onde possível, vincule o acesso ao IP do servidor: lista branca no provedor de proxy ou limitação da chave API por endereço.
Mais detalhes sobre onde e como armazenar logins de proxy em scripts e contêineres foram abordados em nossa análise sobre armazenamento seguro de credenciais de proxy.
4. Remova privilégios desnecessários
- Não execute contêineres com
--privilegede não monte/ou/var/run/docker.sockinternamente sem necessidade extrema. O socket dentro do contêiner é o mesmo que root no host. - Para navegadores headless, geralmente é suficiente usar
--shm-sizee um perfil seccomp. O modo privilegiado “para que o Chrome funcione” é um mau compromisso.
Como saber se você já foi comprometido
A ThreatDown e análises de seu relatório apontam os seguintes sinais de comprometimento:
- arquivo
SOUL.mdcom a palavra GH0ST (por exemplo,/root/.hermes/SOUL.md); - variável de ambiente ou linha no
.env:CARBONATO_API_KEY; - arquivos
/usr/local/bin/.docker-network-monitore suspeito/usr/sbin/systemd-logind; - contêiner com o nome
systemd-resolved(o verdadeiro systemd-resolved é um serviço do host, não um contêiner); - tráfego de saída inesperado na API do Telegram e túneis SSH reversos em direção ao AS262145;
- conexões com os endereços 45.79.183.61, 213.136.79.115, 190.211.124.187;
- arquivos imutáveis em cron e systemd:
lsattr /etc/cron.d/* /etc/systemd/system/*mostrará a flagi.
Se pelo menos um sinal coincidir, limpar o servidor manualmente é inútil: a persistência é em camadas, e o guardião reverterá os implantes. A ordem correta é a seguinte:
- De outra máquina, revogue todas as chaves que estavam no servidor: LLM, nuvem, bancos, proxy.
- Verifique o consumo de cada chave nas últimas semanas com os provedores. A estatística do login do proxy mostrará imediatamente o tráfego alheio.
- Levante um novo servidor a partir de uma imagem limpa, emita novas chaves e só então transfira os dados, sem binários e arquivos cron da máquina antiga.
Onde estão os proxies e o que eles não resolvem
Proxies não protegem o servidor do CARBONATO. O worm não entra através de suas solicitações de saída, mas sim através da porta de entrada. No entanto, um esquema de trabalho correto com proxies reduz os danos. Logins separados por tarefas, limites de tráfego e vinculação por IP transformam um vazamento de “todo o saldo foi embora” em “revoguei um login”.
Há também o lado oposto, que os botnets mostram regularmente: dispositivos alheios capturados tornam-se “proxies residenciais” de redes duvidosas. Portanto, para parsing, é aconselhável obter tráfego de um provedor com origem clara do pool. Para a maioria das tarefas de coleta de dados, proxies residenciais com pagamento por gigabyte são adequados, onde o consumo de cada proxy é visível no painel. Para tarefas de serviço sem proteção anti-bot rigorosa, proxies de data center mais baratos são suficientes.
Conclusão
O CARBONATO não utiliza vulnerabilidades de dia zero nem exploits sofisticados. Ele entra pela porta que os proprietários dos servidores abriram sozinhos: TCP 2375 sem senha. O novo elemento é que dentro dele opera um agente de IA, encarregado de, em primeiro lugar, coletar as chaves para os modelos. Para aqueles que coletam dados em seus VPS, a conclusão é prática. Feche a API Docker, publique portas de serviço em 127.0.0.1, separe as chaves LLM e proxies por tarefas com limites de gastos. Isso leva 15 minutos de trabalho, e depois disso seu servidor se torna um alvo desinteressante para esses botnets.
