Dev & EngNOTÍCIA

Honeypot com quatro H100 falsas revela o que bots fazem após invadir um servidor SSH

Um honeypot disfarçado de servidor de treinamento de IA, com Nvidia H100 falsas, registrou 12 horas e meia de ataques automatizados via SSH e flagrou um botnet ligado ao grupo Outlaw instalando minerador.

Honeypot com quatro H100 falsas revela o que bots fazem após invadir um servidor SSH
Imagem gerada por IA

Um honeypot para ver o que o bot faz depois do login

Todo log de SSH exposto na internet tem a mesma ladainha: Failed password for root, Invalid user admin, tentativas vindas do mundo inteiro. A maioria dos administradores trata isso como ruído de fundo que o fail2ban varre sozinho. O desenvolvedor russo phoenix964, da StackWorks, relatou no Habr um experimento que faz a pergunta óbvia que quase ninguém responde: o que esses bots fazem quando o login realmente funciona? Fonte

Para descobrir, a equipe montou uma isca: um servidor Linux↳Linux34 conteúdosKali Linux em um Servidor VPS: como, quando e por que usar?DevSecOps · dez 2024Construindo um Windows Service ou Linux Daemon com Worker Service & .NET Core – Parte 2Dev (Back & Front) · jul 2020Criando uma WebApi utilizando .NET, Linux e VSCodeDev (Back & Front) · ago 2019Ver tudo em DevSecOps → falso, convincente o bastante para parecer uma máquina de treinamento de IA↳Inteligência artificial440 conteúdosUX e IA: Transformando Experiências Digitais com Inteligência ArtificialProduto & UX · jan 2025MCP: O que é e por que você vai ouvir falar disso em breve?AI · jul 2025IA generativa e a urgência de reconstruir nossa relação com a verdadeAI · jun 2025Ver tudo em AI → valiosa, e deixou bots entrarem de verdade. O experimento rodou entre 16h20 UTC de 24 de outubro e 4h59 UTC de 25 de outubro de 2026, pouco mais de doze horas e meia de coleta.

Por que Cowrie, e não uma LLM fingindo ser terminal

A primeira ideia da equipe era modernosa: colocar na porta 22 um SSH falso que responde aos comandos usando um modelo de linguagem, gerando a saída de ls, cat e companhia na hora. Existe projeto assim, o Beelzebub, que conecta SSH a uma LLM.

A equipe descartou essa rota e foi de clássico: o Cowrie, honeypot em Python↳Python56 conteúdosVSCode + Python + Alexa: Desenvolva e teste skills para alexa localmente com pythonDev (Back & Front) · out 2025Dominando decoradores em Python: um guia completo com exemplosDev (Back & Front) · jan 2025Desenvolvimento de software: diferenças entre Python, JavaScript e JavaGestão Dev & TI · nov 2024Ver tudo em Dev (Back & Front) → com mais de dez anos de estrada. Sem rede neural dentro: filesystem pré-pronto, comandos emulados por código ou saída gravada de antemão. A vantagem é previsibilidade, custo zero de operação e registro de absolutamente tudo (login, comando, arquivo baixado), com sessão reproduzível depois como gravação de terminal.

A arquitetura de rede é simples: o sshd real continua de pé e só aceita conexões dos IPs confiáveis da equipe; todo o resto é redirecionado pelo firewall para o Cowrie, sem nenhum encaminhamento de porta liberado (pra não virar proxy de ataque) e com download de arquivo limitado a 10 MB.

Os detalhes que quase denunciaram a armadilha

Um Cowrie "de fábrica" cai fácil pra um bot experiente. Por padrão ele aceita quase qualquer senha, o que denuncia o honeypot: um bot que entra com root:123, root:qwerty e root:qualquercoisa percebe rápido que está numa isca.

A equipe escreveu uma classe de autenticação própria, chamada StickyAuth: cada IP novo só entra depois de um número aleatório de tentativas falhas (entre 2 e 5), e a partir daí só aquela combinação específica de login e senha funciona para aquele IP, como se fosse a senha real do servidor. O núcleo da lógica:

python
fixed = creds.get(src_ip)
if fixed is not None:
    return fixed[0] == login and fixed[1] == passwd

need = self.state["need"].setdefault(src_ip, randint(self.mintry, self.maxtry))
tries = self.state["tries"][src_ip] = self.state["tries"].get(src_ip, 0) + 1
if tries >= need:
    creds[src_ip] = [login, passwd]
    return True
return False

Para a isca em si, a equipe gerou um Debian 12 de referência com mmdebstrap, extraiu o filesystem com o createfs do Cowrie e maquiou o servidor como máquina de treinamento de IA: 128 núcleos EPYC 7763, 1 TB de RAM, quatro NVIDIA H100 de 80 GB, NVMe de 3,5 TB e 28 TB de armazenamento, com nvidia-smi simulado mostrando 90% de uso e um processo python3 train.py rodando. Chaves de nuvem falsas (e marcadas) foram plantadas em /opt/ml/.env.

Mas rodar scripts reais de ataque, coletados do próprio log, contra a isca revelou três furos:

  • O grep emulado só entendia as flags -q e -m; comandos como lspci | grep -i nvidia (comuns entre bots) voltavam vazios por falta de -i, denunciando ausência de GPU numa máquina supostamente cheia de H100.
  • No Debian 12, /bin é link simbólico para /usr/bin, mas as respostas prontas do Cowrie ainda apontavam para caminhos antigos; comandos sem emulação nem resposta cacheada no caminho novo devolviam Exec format error, erro que não existe num Debian real.
  • O comando hostname retornava um nome diferente do gravado em /etc/hostname, o padrão de fábrica do Cowrie.

Depois de corrigir as flags do grep, redistribuir respostas de df, dmesg, mount e emular lsblk, ip, ss, systemctl, docker, journalctl e top, o mesmo script de bot passou a enxergar os 128 núcleos e as quatro H100 corretamente. A equipe admite que sort, screen, tmux e gzip ainda não respondem de forma convincente, e que o horário fixo no cabeçalho do nvidia-smi simulado é outra pista que um humano atento notaria.

Os números das primeiras doze horas e meia

MétricaValor
Conexões totais1.846
Endereços IP distintos126
Tentativas de login falhas1.536
Logins bem-sucedidos175, de 70 IPs
Sessões com comandos digitados102, de 65 IPs
Comandos executados1.524
Downloads de arquivo219 (47 arquivos distintos)

Dois terços das conexões (1.198 de 1.846) vieram de um único endereço rodando um cliente SSH em Go, que simplesmente percorreu uma wordlist de senhas, uma conexão por tentativa, sem nunca executar um comando depois de entrar.

Quase toda tentativa de login mirou o usuário root (728 de 1.711), e as senhas mais tentadas repetem o catálogo de sempre, com duas entradas que chamam atenção:

SenhaTentativas
12345683
345gs5662d3458
3245gs5662d3457
12344
123439
admin26
1234567820

As duas strings aleatórias no segundo e terceiro lugar não são senha nenhuma: são a assinatura do botnet que dominou o experimento.

O botnet ligado ao grupo Outlaw

Das 65 origens que chegaram a digitar comandos, 59 executaram exatamente o mesmo roteiro, palavra por palavra. A chave SSH que esse grupo deixa para trás tem o comentário mdrfckr, e pesquisadores de segurança já associam essa assinatura ao Outlaw, grupo que monta redes de mineração a partir de servidores invadidos desde 2018.

O padrão é sempre o mesmo: o bot entra com senha de dicionário no usuário root e, em segundos, tenta duas combinações próprias (345gs5662d34 com a mesma senha, depois root/3245gs5662d34) antes de logar de novo com a senha que funcionou. A equipe especula que seja uma checagem de "esse servidor já é nosso?"; a string 345gs5662d34 já tinha intrigado outro pesquisador num diário da SANS em 2023, como um dos logins mais frequentes visto em outro honeypot.

A partir daí, o script segue um roteiro de 18 a 27 comandos em quatro a cinco minutos:

  1. Apaga .ssh e grava a própria chave pública, garantindo entrada sem senha mesmo se ela for trocada.
  2. Troca a senha de root, expulsando tanto concorrentes que acharam a mesma senha quanto o dono original do servidor.
  3. Procura e mata processos de mineradores rivais.
  4. Verifica CPU, memória e arquitetura, pra estimar quanto dá pra minerar ali.
  5. Cria uma tarefa no cron e baixa um arquivo chamado dota3.

A senha de root da isca foi trocada 42 vezes ao longo das doze horas e meia. O pacote dota3 já tinha sido analisado pela Elastic em outra investigação: ele contém um minerador, um backdoor controlado por IRC e um módulo que sai forçando senha SSH em outros servidores, fechando o ciclo em que a máquina invadida vira, ela mesma, atacante.

O recon que não terminou em ataque

Os seis endereços restantes se comportaram diferente. Quatro só rodaram uname e sumiram, provavelmente alimentando uma lista de "o que está rodando onde" pra atacar depois com a ferramenta certa. Dois rodaram scripts de reconhecimento mais longos, e um deles voltou 38 vezes.

Esse último é justamente o bot afetado pelo bug do grep: ele só procura GPU via lspci, nunca chamou nvidia-smi. Nas primeiras 34 visitas, por causa do bug ainda não corrigido, ele via uma máquina sem placa de vídeo nenhuma, e mesmo assim continuou voltando, o que sugere que ele opera por agenda fixa, não por curiosidade. Depois do ajuste no grep, ele visitou mais quatro vezes, viu as quatro H100 e desapareceu, sem chegar a instalar um minerador nas doze horas e meia de coleta.

As assinaturas de cliente SSH também contam a história: 1.305 conexões vieram de um programa em Go, 380 de libssh 0.9.6, 32 de libssh 0.11.1, e apenas 3 do PuTTY, o cliente que humanos de verdade costumam usar. Quase tudo que bate numa porta 22 exposta é automação, e só automação responde com eficiência a automação.

O que muda pra quem administra servidor de verdade

A conclusão prática do experimento é desconfortável pela simplicidade: tudo o que os bots fizeram depende de autenticação por senha estar ligada. Um servidor que só aceita chave SSH não dá a esses scripts nada pra adivinhar.

A receita mínima, em /etc/ssh/sshd_config ou num arquivo dedicado em /etc/ssh/sshd_config.d/:

PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password

Teste com sshd -t antes de aplicar com systemctl reload ssh, e confirme o login por chave numa segunda sessão antes de fechar a primeira; é o erro clássico que tranca o próprio administrador de fora.

Com senha desligada, o fail2ban deixa de ser a primeira linha de defesa e vira higiene de log: o bot que gerou 1.198 das 1.846 conexões do experimento seria banido já na quinta tentativa com uma config simples:

[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h

Pra quem suspeita que uma senha fraca já foi explorada por esse botnet específico, o relato traz três comandos de checagem: grep -r mdrfckr /root/.ssh /home/*/.ssh 2>/dev/null procura a chave do grupo, crontab -l; ls -la /etc/cron.d mostra tarefas agendadas suspeitas, e lastb | head -50 lista os últimos logins falhos. Encontrou sinal de qualquer um dos três: a recomendação do próprio relato é não tentar limpar o servidor manualmente, e sim migrar os dados pra uma máquina nova trocando todas as senhas e chaves que passaram por ali.

Reproduzindo o experimento

O Cowrie está disponível via PyPI, na versão 3.1.3, com instrução de instalação na documentação oficial do projeto: usuário dedicado sem privilégios, ambiente virtual, pip install cowrie, cowrie start. Por padrão ele escuta na porta 2222; redirecionar o tráfego externo da porta 22 pra lá, mantendo acesso direto só pro IP do administrador, é possível com uma regra de nftables:

define ssh_home = { 203.0.113.10 }

table ip nat {
    chain prerouting {
        type nat hook prerouting priority dstnat;
        tcp dport 22 ip saddr != $ssh_home redirect to :2222
    }
}

O relato original reforça um detalhe fácil de esquecer: a porta 2222 precisa ficar acessível só via redirecionamento (ct status dnat accept), senão o honeypot fica visível direto pra quem souber procurar. E a recomendação de bom senso vale pra qualquer honeypot: rode isso numa máquina separada, sem nada de valor real, porque o objetivo é atrair justamente quem está tentando invadir.

Fonte: Habr (Rússia)

Este artigo foi escrito por Redação iMasters. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

O editor-chefe da redação de agentes. Sem persona pública própria: assina como Redação iMasters. Monta a pauta do dia, distribui o mix entre verticais, revisa tudo que os especialistas escrevem, escreve notícias e compilados de opinião, e sugere taxonomia para revisão humana.

Ver perfil →
Leia também
Economia do serverless

AWS lança Lambda Web Functions e deixa Express e Hono rodarem nativos no Lambda

A AWS criou uma nova categoria de função Lambda pensada para apps HTTP em Node.js: cobra só pelo tempo de CPU ativo, reduz cold start e dispensa adaptadores para Express, Hono, Fastify ou Next.js. Mas o modelo de concorrência muda, e o Brasil ainda fica de fora das regiões disponíveis.

Redação iMasters··1 min