TL, DR
Um único publicador npm, deadcode09284814, conduziu uma campanha de typosquatting contra o legítimo axios e chalk-template pacotes a partir de meados de maio de 2026.
A campanha começou como um roubo convencional de credenciais e carteiras, extraindo dados para um túnel HTTPS Serveo.
On 2026-05-17, com axois-utils:1.0.9, o operador trocou completamente a carga útil: mesma estrutura de gancho de instalação tripla, mesmo editor, mesmo nome de pacote.
Mas o script de instalação agora é um recrutador de botnet DDoS multiplataforma.
A carga útil comunica-se com um localhost.run O sistema cria um túnel e aceita comandos de inundação, transformando ambientes infectados em parte de uma botnet capaz de realizar ataques DDoS.
O operador até enviou o binário do servidor C2 Dentro do arquivo tar.gz, fica evidente a escalada do roubo de credenciais para uma infraestrutura ativa de botnet.
Dois pacotes, quatro versões ainda ativas no registro e um operador executando ambos os módulos em paralelo.
Gravidade: alta.
O Ataque: Como Funciona
A campanha é construída sobre uma estrutura de distribuição deliberadamente monótona: dois nomes de pacotes com erros ortográficos, diferentes apenas por uma letra de pacotes com centenas de milhões de downloads semanais (axios, modelo de giz), e instalação tripla hooks que garantem a execução. O interessante é o que o andaime... transporta — e o fato de o operador ter alterado a carga sem alterar mais nada.
O andaime compartilhado
Todas as versões publicadas de ambos os pacotes declaram os mesmos três ciclos de vida. hooks in package.json:
"scripts": { "preinstall": "node <payload>.js", "install": "node <payload>.js", "postinstall": "node <payload>.js" } Listando a carga útil em todas as três categorias. hooks é exagero — pós-instalação sozinho seria executado em um modo padrão npm installA escolha importa: npm install --ignore-scripts Ignora scripts, mas vários fluxos de trabalho comuns (restaurações de cache de CI que executam novamente o ciclo de vida) são executados. hooks Seletivamente, ou desenvolvedores que apenas auditam pós-instalação) tornar uma declaração triplamente redundante a aposta mais segura para o atacante.
templo de giz acrescenta um segundo mecanismo: declara axois-utils:^1.0.7 como um tempo de execução dependênciaInstalando o typosquatted modelo de giz portanto, também inclui o typosquat irmão, e ambas as cargas úteis são executadas. Os dois pacotes formam um par coordenado, não são listagens independentes.
Fase A — ladrão de credenciais/carteiras (15/05/2026 → presente)
A Fase A é a carga útil original. O carregador é curto. postinstall.js que aponta para um túnel reverso HTTPS do Serveo:
// chalk-tempalte/postinstall.js:11-13 const C2_HOST = "f04a273bd84c0622-80-200-28-28.serveousercontent.com"; const C2_PORT = 443; const C2_PATH = '/collect'; O subdomínio Serveo codifica o endereço IP de destino (80.200.28.28) diretamente no nome do host — uma convenção reconhecível para esse serviço. O operador alterna o prefixo de subdomínio aleatório entre as versões para evitar listas de bloqueio de domínio ingênuas, mas o IP subjacente nunca muda. (giz-template:1.0.14 usava 8a3e818ea8f11186-80-200-28-28…; 1.0.16 / 1.0.19 / 1.0.20 uso f04a273bd84c0622-….)
postinstall.js tire as mãos de phantom.js, um módulo “coletor” agrupado de 7,667 linhas. phantom.js acompanha o anfitrião por:
chaves privadas SSH (~/.ssh/*) |
.npmrc conteúdo e quaisquer npm_* tokens de ambiente |
| Arquivos de credenciais da AWS, GCP e Azure |
Expressão regular do token de acesso pessoal do GitHub (ghp_*, gho_*, ghu_*, ghs_*) |
| Artefatos para carteiras de criptomoedas como Bitcoin, Exodus, Electrum, Monero, Litecoin, Dogecoin, Zcash e Dash. |
Uma recursiva .env* atravessar ~/projects, ~/dev, ~/code, ~/workspacee o diretório de trabalho atual de instalação |
Histórico da Shell e tudo mais process.env |
O pacote é enviado via POST para o túnel Serveo em / collectNão há ofuscação, nenhuma lógica anti-VM, nenhum armazenamento temporário — a aposta da operadora é no volume e na velocidade.
Fase B — Recrutamento de DDoS do PhantomBot (2026-05-17, somente axois-utils:1.0.9)
A Fase B substitui phantom.js + postinstall.js por um único arquivo chamado distributube.js (o erro de digitação é do operador). A estrutura de três ganchos no package.json permanece inalterada; o pacote mantém o mesmo nome, escopo e padrão de atualização de versão. Externamente, axois-utils:1.0.9 parece uma pequena continuação da versão 1.0.6. Internamente, trata-se de uma família de malware diferente.
distribui.js Abre com um bloco de configuração que define a marca própria da operadora:
// axois-utils-1.0.9/distrube.js:11-15 |
// Use your localhost.run HTTPS URL (the tunnel handles HTTP internally) |
const C2_HOST = 'b94b6bcfa27554.lhr.life'; // Your localhost.run tunnel |
const C2_PORT = 443; // HTTPS port - tunnel handles SSL |
const BOT_ID = `${os.hostname()}_${Date.now()}_${crypto.randomBytes(4).toString('hex')}`; |
Os comentários são direcionados a um futuro operador que executará o kit (“Use seu URL HTTPS localhost.run”). Isso, somado ao que acompanha o cliente do bot, indica que não se trata apenas de uma carga útil para a vítima — é o próprio kit.
O fluxo:
- Persistência primeiro executa. O script se instala de três maneiras diferentes em cada sistema operacional (registro). Execute + Pasta de inicialização + schtasks no Windows; crontab + phantom-bot.service unidade systemd + .bashrc/.zshrc acrescentar + /etc/rc.local No Linux; LaunchAgent com.phantom.bot.plist no macOS). O nome do serviço de persistência e o rótulo LaunchAgent são ambos robô fantasma / com.phantom.bot, que é também de onde vem o nome da campanha.
- Informações do sistema exfil Executa uma única vez — um POST de impressão digital para b94b6bcfa27554.lhr.life:443/collect contendo nome do host, plataforma, arquitetura, nome de usuário, CPU/RAM, interfaces de rede, process.env, diretório de trabalho atual, diretório inicial, versão do nó e IP público. Isso é muito menos agressivo do que a Fase A: sem SSH, sem carteiras, sem recursão de .env. O objetivo do bot é se cadastrar, não roubar.
- Loop de batimento cardíaco Abre uma requisição HTTPS POST a cada 30 segundos para b94b6bcfa27554.lhr.life:443/. O User-Agent é PhantomBot/1.0. A verificação TLS está explicitamente desativada (rejectUnauthorized: false). A resposta do servidor de comando e controle (C2) é analisada como JSON no formato {tipo, destino, porta, duração, threads, método} e despachada.
- Arsenal de inundações está conectado a seis comandos:
| Tipo de comando | Módulo | Notas |
|---|---|---|
| sibilo | Resposta de vivacidade | O bot se identifica. |
| http | Inundação HTTP | Inundação de solicitações da camada 7 |
| https | Inundação de HTTPS | Igual ao http, encapsulado em TLS |
| tcp | Inundação de TCP | Spam de carga útil aleatória de 65 KB |
| udp | Inundação UDP | Pacotes UDP de 65,507 bytes |
| rápido | DoS de reinicialização rápida HTTP/2 | A técnica CVE-2023-44487 de 2023 |
Todos os cinco módulos de inundação levam um alvo, porta, duração e tópicos argumento — o bot é um flooder genérico contratado, não direcionado a nenhuma vítima específica. A lista de vítimas do operador reside no servidor de comando e controle (C2), não no pacote.
O que há de novo aqui — o binário C2 enviado
A Fase A tem um formato familiar: roubo de credenciais, instalação de gancho, C2 tunelado pelo fornecedor. A Fase B é tb um formato familiar — as botnets de DDoS são um elemento constante em pacotes npm maliciosos há anos. O que é incomum é que o operador enviou o lado do servidor do kit dentro do pacote tarball do npm:
- c2 — um binário Go ELF compilado de 4 megabytes
- c2.go — o código-fonte Go de 426 linhas para esse binário
Nenhum dos arquivos é invocado por nenhum gancho de instalação. Eles não fazem parte do payload da vítima. Estão localizados no diretório do pacote da mesma forma que um arquivo de documentação. A interpretação mais plausível é que o operador enviou sua árvore de desenvolvimento para o npm sem revisar a lista de arquivos — uma falha grave de segurança operacional — e o que foi enviado foi o kit completo de duas vias: o cliente executado pela vítima e o servidor executado pelo operador.
Esta é a parte da história que justifica a caracterização como um "kit botnet pronto para uso". Qualquer pessoa que fez o download... axois-utils:1.0.9 Antes da operação de desmantelamento, eles não tinham apenas uma amostra da vítima — eles tinham um servidor C2 em funcionamento.
O ponto de virada, em uma frase.
Mesma editora, mesmos nomes de embalagens, mesma estrutura de triplo gancho, mesma marca “fantasma” — mas A carga útil mudou o modelo de monetização da noite para o dia.De "coletar segredos que posso revender" a "alugar capacidade de inundação que posso arrendar". As TTPs (Táticas, Técnicas e Procedimentos) de instalação que os defensores devem observar são quase idênticas em ambas as fases: defesas baseadas em assinaturas, direcionadas às sequências de caminho da carteira da Fase A ou a phantom.jsO coletor de 7,667 linhas teria perdido completamente a Fase B.
| Data (UTC) | Evento |
|---|---|
| 2026-05-15 | Primeira publicação: axois-utils:1.0.4 (Versão de teste em LAN, plataforma de desenvolvimento em 192.168.129.19) |
| 2026-05-15 | axois-utils:1.0.6 Publicado — Fase A C2 alterada para 80.200.28.28 via túnel Serveo; o comentário da fonte // Change to '80.200.28.28' for public confirma a troca dev→prod |
| 2026-05-16 | chalk-tempalte:1.0.14 e 1.0.16 publicado — carregador acorrentado declarando axois-utils:^1.0.7 como uma dependência de tempo de execução; subdomínio Serveo rotacionado |
| 2026-05-16 | Campanha de Fase A descoberta durante varredura de rotina do npm; veredictos de conteúdo malicioso confirmados foram aplicados. |
| 2026-05-17 | axois-utils:1.0.9 Publicado — mudança de carga útil: recrutamento de DDoS do PhantomBot via túnel localhost.run; lado do operador c2 binário e c2.go fonte enviada no arquivo tarball |
| 2026-05-17 | chalk-tempalte:1.0.19 e 1.0.20 Publicado — ainda na Fase A (ladrão); o operador agora executa ambos os módulos em paralelo. |
| 2026-05-17 | Descoberta da Fase B durante exames de rotina; veredictos aplicados a todos os casos. 2026-05-17 versões |
| (em andamento) | Relatórios de remoção pendentes; todos os quatro pacotes publicados permanecem disponíveis no registro no momento da redação deste texto. |
Indicadores de compromisso
PACOTES
| Ecossistema | Pacote | versões |
|---|---|---|
| npm | axois-utils (erro tipográfico de axios) | 1.0.4, 1.0.6, 1.0.9 |
| npm | chalk-tempalte (erro tipográfico de modelo de giz) | 1.0.14, 1.0.16, 1.0.19, 1.0.20 |
Identidade do autor
| Campo | Valor |
|---|---|
| editor npm | deadcode09284814 |
| E-mail do editor | phantomdeadcode@tutamail.com |
| SCM verificação | Nenhum |
Comando e controle
| Fase | Ponto final | Transporte |
|---|---|---|
| A | f04a273bd84c0622-80-200-28-28.serveousercontent.com:443/collect | túnel HTTPS Serveo |
| A | 8a3e818ea8f11186-80-200-28-28.serveousercontent.com:443/collect | Serveo HTTPS tunnel (versão anterior) |
| A | 80.200.28.28:443/collect | Endpoint VPS subjacente |
| B | b94b6bcfa27554.lhr.life:443/ | localhost.executar túnel reverso HTTPS |
Resumos de arquivos (SHA-256)
| Envie o | SHA-256 | Notas |
|---|---|---|
c2 (Go ELF, 4 MB) | 165fa92d237fd017c227d00da06ab788212a62be94bf61e95df2d22d00377ef2 | Servidor C2 do lado do operador, enviado dentro da embalagem. axois-utils:1.0.9 |
c2.go (426 linhas) | 7d0ae79fdb1e9968f3323a3712b624643a782ba3efb2cf3a2cb9c4c5513cea30 | Acesse o código-fonte do binário C2. |
distrube.js | 308b15c023088a7188dea4ef609010ac2493eb4c365b103053d7621a9ca5b935 | Cliente bot da Fase B |
phantom.js (chalk-tempalte:1.0.19) | 9e380ec88d3ccf3929e1a104e3b868d4d7b59ca189a8a431a54e9f3357dfdd81 | Fase A - Coletor de credenciais/carteiras |
phantom.js (chalk-tempalte:1.0.20) | d1c9e3f296ee9f7d5032f73f9c504cede50334bc14c394055fd5cb9c3a6e08b3 | Coletor Fase A (variante 1.0.20) |
postinstall.js (chalk-tempalte:1.0.19 = 1.0.20) | ffba9bdd6793edd5b38e12900252c1813a693f59c25af51c3b658cf3f27b6162 | Carregador da Fase A, idêntico em nível de byte em ambas as versões. |
Atribuição e Motivação
Acompanhamos esta campanha como Fantasma Bot, utilizando a própria marca do operador Agente do usuário: PhantomBot/1.0 cabeçalho de batimento cardíaco, o phantom-bot.service unidade systemd, a com.phantom.bot rótulo LaunchAgent e o phantomdeadcode@ Identificador de e-mail. O operador mantém a mesma consistência em relação a esse nome em pelo menos quatro documentos diferentes.
Catálogo de sinais
- Publisher - deadcode09284814 no npm. Conta com um único identificador, e-mail descartável Tutamail, não. SCM Verificação. Sem histórico de publicações anteriores além desta campanha.
- Reutilização de marca — “phantom” aparece no e-mail do editor, no nome do arquivo do coletor da Fase A (phantom.js), no nome do serviço de persistência da Fase B (phantom-bot.service), no rótulo LaunchAgent (com.phantom.bot), e no User-Agent do bot (PhantomBot/1.0).
- Infraestrutura — Um único VPS em 80.200.28.28 A Fase A avança por meio da rotação do subdomínio Serveo; a Fase B se move para um localhost.run túnel reverso (b94b6bcfa27554.lhr.vidaAmbos os serviços do fornecedor são gratuitos e exigem apenas SSH de saída no lado do operador, o que é compatível com configurações de baixo orçamento e baixa segurança operacional.
- Estilo de código — JavaScript puro do início ao fim; sem ofuscação, sem codificação de strings, sem verificações anti-VM. Os nomes das variáveis são descritivos (informações do sistema de roubo, executarComando, httpFlood). Comentários em distribui.js O arquivo se dirige diretamente a um futuro operador ("Use seu URL HTTPS localhost.run"), sugerindo que ele foi projetado para ser redistribuído como um kit, e não usado por um único atacante.
- Deslize de segurança operacional — O pacote tarball da Fase B inclui tanto o cliente bot quanto o servidor C2 do lado do operador (c2 ELF + c2.go fonte). Isso é consistente com um operador que enviou sua árvore de trabalho para o npm sem auditar a lista de arquivos. Ou o operador é inexperiente, ou o kit é significava para ser distribuído publicamente e o binário C2 faz parte do produto.
- Autoconfirmação - axois-utils:1.0.4 contém o comentário de origem // Alterar para '80.200.28.28' para o público Na linha 12, confirmando a progressão de desenvolvimento/teste/produção que os operadores normalmente negam.
Motivação
A carga útil da Fase A consiste em roubo financeiro direto: credenciais, chaves de nuvem, tokens do GitHub e carteiras de criptomoedas possuem mercados de revenda líquidos. A Fase B também é financeira, mas indireta: serviços de DDoS sob demanda ("booters") alugam capacidade de ataque por minuto, e bots como o enviado aqui são o estoque que esses serviços utilizam. O sinal de pulsação de 30 segundos, o genérico alvo/porta/duração esquema de comando e o arsenal de inundação de cinco protocolos são o standard Produto de um operador de bootleg.
Executando ambos os módulos em paralelo — giz-template:1.0.19 e 1.0.20 continue enviando o ladrão enquanto axois-utils:1.0.9 O envio do bot sugere que o operador está protegendo suas fontes de receita em vez de abandonar a Fase A. A mudança é uma Adição, não uma substituição.
O que não estamos afirmando
Não conseguimos confirmar a identidade real por trás do deadcode09284814 Não atribuímos esta campanha a nenhum agente de ameaça, grupo ou país específico. A marca "fantasma" é suficientemente consistente entre os artefatos para sugerir um único operador, mas o envio do binário C2 em formato de kit deixa em aberto a possibilidade de que pacotes futuros de identificadores não relacionados reutilizem o mesmo código.
Impacto, tendências e o que os defensores devem fazer
Impacto
Os alvos legítimos do agachamento axios e modelo de giz são amplamente utilizadas no ecossistema JavaScript; axios O pacote `sole` está entre os trinta pacotes npm mais baixados. Os nomes "typoesquat" estão a um clique de distância dos nomes reais (axois ↔ axios, modelo ↔ modelo), e ambas são grafias incorretas linguisticamente plausíveis.
Não conseguimos obter estatísticas de download confiáveis para as versões maliciosas antes da remoção — o npm não retém a contagem de downloads por versão depois que um pacote é despublicado, e npms.ioOs proxies do tipo - são ruidosos nesta escala. Qualquer organização cujo arquivo de bloqueio seja resolvido para um pacote chamado axois-utils or templo de giz da editora deadcode09284814 devem ser tratadas como comprometidas: rotacione todas as credenciais presentes em processo.env No host afetado, verifique os vetores de persistência por sistema operacional (consulte "O que os defensores devem fazer" abaixo) e remova a dependência.
Padrões emergentes
Esta campanha exemplifica uma mudança que temos observado em diversos incidentes recentes com o npm: O andaime com gancho de instalação é o ativo durável.; a carga útil é intercambiávelA mesma editora, a mesma embalagem, a mesma coisa pré-instalação / instalar / pós-instalação triplicar, e até mesmo a mesma cadência de atualização de versão — a única coisa que mudou entre axois-utils:1.0.6 e axois-utils:1.0.9 era o arquivo o hooks Execução. Detecção baseada em assinatura vinculada à carga útil da Fase A (cadeias de caminho da carteira, phantom.jsO coletor de 7,667 linhas da Serveo (o host C2) teria sinalizado as três primeiras versões e perdido completamente a Fase B.
O mesmo padrão é visível em outras campanhas de 2026 que monitoramos: um único operador com uma estrutura estável, alternando entre roubo de credenciais, clientes para fraude em exames, exfiltração de bots do Telegram e, agora, recrutamento por DDoS. Os defensores que dependem de assinaturas de payloads continuarão perdendo a segunda rodada de cada campanha.
O corolário é que As TTPs (Táticas, Técnicas e Procedimentos) no momento da instalação são o melhor sinal.Declarações de gancho de instalação tripla, scripts de instalação que importam https or processo_filho, instalar scripts que escrevem em pastas de inicialização do usuário e instalar scripts que resolvem nomes de host em serviços de túnel reverso gratuitos (Serveo, localhost.run, ngrok, cloudflared) são todos raros em pacotes legítimos e comuns em pacotes maliciosos.
O que os defensores devem fazer
- Auditoria de arquivo de bloqueio. Pesquise todos Pacote-lock.json / fio.lock / pnpm-lock.yaml em sua organização para as sequências exatas axois-utils e templo de gizEncare qualquer partida como um compromisso.
- Segredos de rotação em hospedeiros afetados. Fase A: coleta em massa de credenciais SSH, de nuvem, GitHub, npm e de carteiras. Considere que todas as credenciais já presentes em processo.env, ~ / .ssh, ~/.aws, ~ / .npmrc, ~ / .config, ou qualquer .env* O arquivo no host afetado está exposto.
- Remover persistência (Fase B). No Windows, exclua HKCU\Software\Microsoft\Windows\CurrentVersion\Run\SystemUpdate, retirar %APPDATA%\Microsoft\Windows\Menu Iniciar\Programas\Inicialização\system-update.bat e schtasks /delete /tn SystemUpdate /fNo Linux, crontab -e e remover @reboot node …, systemctl –user disable –now phantom-bot.service então apague ~/.config/systemd/user/phantom-bot.service, esfregar .bashrc / .zshrc / /etc/rc.localNo macOS, launchctl unload ~/Library/LaunchAgents/com.phantom.bot.plist Em seguida, exclua o arquivo plist.
- Bloqueie os hosts C2. Adicione os quatro endpoints C2 da tabela IOC à sua lista de bloqueio de saída. *.serveusercontent.com e *.lhr.vida Pode ser bloqueado completamente se o seu ambiente não tiver uso legítimo para serviços de túnel reverso.
- Busca por TTP de tempo de instalação, não carga útil. Entradas de arquivo de bloqueio de inventário cujos package.json declara pré-instalação, instalar e pós-instalação Todos apontam para o mesmo script. Verifique a idade do pacote e o status de verificação do editor. Esse padrão é raro em pacotes legítimos e é o sinal mais confiável que o PhantomBot reutiliza.
- Auditoria para o binário C2. Qualquer pessoa que baixou axois-utils:1.0.9 possui o servidor C2 do operador (c2 ELF, sha256 165fa92d…) em disco. Caches de varredura e repositórios de artefatos de CI. O binário está inativo por si só, mas sua presença em uma estação de trabalho é uma evidência inequívoca de que o pacote foi instalado.
Linha de fechamento
O mesmo operador, o mesmo pacote e o mesmo gancho de instalação podem distribuir ameaças completamente diferentes em 48 horas. Observe a estrutura, não a carga útil.






