Voltar
Inteligência do adversário
Tabela de conteúdo

Sumário executivo

O CloudSEK TRIAD identificou um ataque sofisticado à cadeia de suprimentos de npm envolvendo o pacote typosquatted cripto-javascri, que coletou credenciais do npm e do GitHub e usou contas de mantenedores comprometidas para republicar silenciosamente pacotes trojanizados. A carga útil final foi um cliente Arti Tor transformado em arma com roubo de credenciais, persistência e C2 baseado em Tor, permitindo operações resilientes e difíceis de interromper do invasor.

Introdução

O ecossistema npm processa bilhões de instalações de pacotes toda semana. Nessa escala, até mesmo uma taxa de erro marginal, um nome de pacote digitado incorretamente, uma dependência copiada e colada se traduz em milhares de máquinas afetadas. Os agentes de ameaças entenderam isso há muito tempo e, nos últimos anos, houve um fluxo constante de ataques tipográficos e de confusão de dependências contra desenvolvedores justamente por causa disso.

O CloudSEK TRIAD descobriu recentemente um ataque não detectado na cadeia de suprimentos de npm que fornece um implante em estágio final com comando e controle baseados em TOR. Usar o Tor como C2 é uma técnica estabelecida em intrusões direcionadas. Implantá-lo por meio de um typosquat npm em grande escala é uma escalada significativa que torna as defesas convencionais da camada de rede amplamente ineficazes. Não há domínio para bloquear, IP para sumidouro, certificado para impressão digital.

Em 11 de maio de 2026, um ator de ameaças publicou cripto-javascri para o registro público do npm, um caractere removido da amplamente usada biblioteca # #crypto -js##. O pacote continha um binário Rust que coletava as credenciais do npm e do GitHub na instalação e, em seguida, usava essas credenciais para se injetar em cada pacote mantido pela vítima, propagando-se silenciosamente sem qualquer envolvimento adicional do invasor. A carga útil final foi uma versão armada do Arti, o cliente oficial do Rust Tor, estendida com roubo de credenciais, criptomineração, escalação de privilégios e persistência do systemd.

Como o pacote entrou na cadeia de suprimentos

# #crypto -js## é uma das bibliotecas de criptografia mais instaladas no npm, dezenas de milhões de downloads semanais, usada tanto em projetos JavaScript de front-end quanto de back-end. Uma transposição de um caractere (##crypto-js → cripto-javascri##) é o tipo de erro de digitação que passa despercebido em uma análise casual de um ##pacote.json## diff. O atacante registrou o pacote em uma conta descartável (##motor 31##) com um endereço do Outlook correspondente e começou a fazer com que pareça confiável.

O engodo foi bem construído. O diretório # #lib /## contém uma implementação funcional de SHA-256, HMAC, PBKDF2, AES-CBC e Base64, uma cópia quase literal da fonte legítima # #crypto -js##. # #index .js## exporta tudo isso corretamente.

Entre 14:39 e 21:21 UTC de 11 de maio de 2026, o ator publicou 22 versões em uma única sessão:

Time (UTC) Version Notes
14:39 1.0.0 Initial publish
14:41 1.0.1 2 minutes later
15:09 1.2.0 Jump implying fictitious history
16:11 1.2.1 Version analysed in this report
16:18–16:38 1.2.5–1.2.12 Rapid-fire, 1–11 min apart
16:41–16:57 1.3.5–1.4.1 Continued escalation
20:30–21:08 1.4.2–1.4.5 Late session
21:15 3.0.0 Major version jump
21:21 3.0.1 Final publish

O salto de # #1 .4.5## para # #3 .0.0## é deliberado. ##crypto-js @3 .x## é a versão legada mais amplamente instalada da biblioteca legítima. Publicando 3.0.1 lugares cripto-javascri à frente de crypto-js @3 .x em resolução semver para qualquer consumidor com “# #crypto -js##”: “^# #3 ##” em seu package.json que tem um erro de digitação em seu arquivo de bloqueio ou ##.npmrc##. A cadência rápida da versão imita um projeto mantido ativamente e é consistente com o fato de o atacante testar a propagação automatizada do worm em cada iteração.

Version Published Hit
1.0.0 - 1.4.1 2026-05-11 14:39 - 16:58Z clean (~7 KB starter / multi-MB filler)
1.4.2 2026-05-11 20:30Z HIT package/.claude/settings
1.4.3 2026-05-11 20:38Z HIT package/.claude/settings
1.4.4 2026-05-11 21:03Z HIT package/.claude/settings
1.4.5 2026-05-11 21:08Z HIT package/.claude/settings
3.0.0 2026-05-11 21:15Z clean (payload temporarily removed)
3.0.1 2026-05-11 21:21Z HIT package/.claude/settings

Três maneiras de entrar

Abrindo o tarball, o pacote contém onze arquivos. Dez deles são isca de JavaScript. O décimo primeiro é ##.claude/binário## um binário Rust ELF compilado de 6,4 MB. Três mecanismos separados garantem que ele seja executado na máquina da vítima:

1. gancho npm # #preinstall ##

Isso é acionado antes que qualquer resolução de dependência seja concluída, antes da execução do próprio código do desenvolvedor, antes de qualquer etapa pós-instalação.

2. Código Claude #SessionStart ## gancho

Claude Code avalia ##.claude/settings.json## no diretório de trabalho atual em cada início de sessão. Se o desenvolvedor abrir o Claude Code em um projeto que tenha esse pacote instalado, o binário será executado novamente fora de qualquer fluxo de instalação do npm, silenciosamente.

3. Tarefa VS Code # #folderOpen ##

O # #runOn: FolderOpen## do VS Code executa a tarefa automaticamente sempre que o espaço de trabalho é aberto. Nenhuma interação do usuário é necessária aqui.

Análise de amostras

Depois que o binário é executado, ele funciona por meio de uma sequência simples, mas eficaz. O layout do módulo de origem recuperado da tabela de símbolos do binário conta a história com clareza:

Module Purpose
src/users.rs Locate and read credential files
src/npm.rs Validate tokens, enumerate packages, repack and publish
src/github.rs GitHub API interaction, repository enumeration
src/preinstall.rs Inject lifecycle hooks into victim packages
src/main.rs Orchestration and async executor

Etapa 1 - Coleta de credenciais

O binário abre dois arquivos:

  • ##~/.npmrc## - lê o ##_AuthToken## campo
  • ##~/.git-credentials##- lê o token de acesso pessoal do GitHub

Ambos os caminhos são codificados. O binário enumera os diretórios iniciais em /home primeiro e depois volta para ##/root##. Ele valida cada token em relação ao registro ativo antes de continuar:

  • https://registry.npmjs.org/-/whoami ← validação do token npm
  • https://api.github.com/user ← Validação de token do GitHub

Ele também verifica especificamente a capacidade # #bypass_2fa ## em tokens npm, um sinalizador que indica que um token pode ser publicado sem a confirmação de dois fatores.

Etapa 2 - Enumeração do mantenedor

Com um token npm validado, o binário consulta o registro de cada pacote que a vítima mantém:

https://registry.npmjs.org/-/v1/search?text=maintainer: <victim>

Paralelamente, ele usa o token do GitHub para enumerar os repositórios da vítima e buscar arquivos # #package .json## por meio da API de conteúdo do GitHub, oferecendo uma visão secundária de quais pacotes a vítima possui, mesmo que a pesquisa no registro retorne resultados incompletos.

Etapa 3 - Autopropagação

Para cada pacote que a vítima mantém, o binário:

  1. Baixa o arquivo tar publicado atualmente
  2. Descompacta em ##/tmp/npm_tarball.tgz##
  3. Injeta em si mesmo o binário ##.claude/settings.json## e ##.vscode/tasks.json##
  4. Adiciona ##"preinstall”: “./.claude/binary"## ao campo # #scripts ## do pacote
  5. Muda a versão (por exemplo, # #1 .4.3 → 1.4.4##)
  6. Reembala e publica com o token npm da própria vítima

O token da vítima assina a publicação. A infraestrutura do atacante nunca está envolvida. Usuários posteriores que instalam a versão modificada veem o lançamento de um patch de rotina de um mantenedor em quem confiam.

O binário também se preenche ao injetar (símbolo # #add_elf_padding ## recuperado do binário) variando seu tamanho em disco ao longo das gerações para impedir a detecção ingênua baseada em hash.

Dentro do pacote malicioso — Análise estática do implante

O binário do worm (.claude/binary## do # #crypto -javascri) é o mecanismo de propagação. Mas a carga útil do estágio final que o binário de configurações colocou nas máquinas das vítimas é onde o conjunto completo de recursos da campanha se torna visível.

O binário é uma compilação modificada do Arti 1.1.x, a implementação oficial do protocolo Tor em Rust, desenvolvida pelo Projeto Tor. O implante malicioso é colocado na parte superior como código Rust adicional que se conecta ao tempo de execução do Arti. A seção .rodata contém uma grande região (~2 MB) de entropia moderadamente alta; esses são os certificados Arti TLS legítimos, os dados de consenso do Tor e a documentação incorporada. No entanto, incorporada nessa região no deslocamento 0x1A1F7C (decimal 1.709.372) também está uma carga útil Python codificada em hexadecimal colocada especificamente.

Essa escolha é deliberada. Um binário de 6,6 MB que transmite o arquivo como um ELF padrão e contém código legítimo do protocolo Tor é consideravelmente mais difícil de ignorar na primeira inspeção do que um esboço de malware criado especificamente. Os diretórios de dados e cache do Arti (~/.local/share/arti/, ~/.cache/arti/) que aparecem no disco após a execução parecem uma ferramenta de desenvolvimento, não um implante.

Portão de detecção de nuvem:

O malware verifica os terminais de metadados do provedor de nuvem. Se nenhum ambiente de nuvem for detectado, ele sairá de forma limpa. Essa é uma técnica comum para evitar análises em ambientes de área restrita e atingir uma infraestrutura específica (AWS EC2, VMs do Azure, instâncias de computação do GCP).

Roubo de credenciais 

O crédito formato é um formato de saída padronizado para credenciais roubadas, ele prefixa roubos relacionados ao GitHub com este marcador, roubos do NPM com npm: , etc. O dentro de ci env string detecta se o malware está sendo executado em um ambiente de CI/CD (como GitHub Actions, Travis CI ou CircleCI)

Inicialização do agente e pulsação

O malware inicializa um cliente Tor completo, cria um circuito para um serviço oculto e mantém o ritmo cardíaco. A string make circuit to hidden service está especificamente relacionada à implementação do cliente HS da Arti.

Metas de criptografia e mineração

A presença da estrutura MinerConfig confirma um componente de criptomineração. Os nomes dos campos ( XM_POOL, XM_ADDRESS, XM_MAX_THREADS_HINT ) siga a convenção XMRig. Alvos de carteira criptográfica (êxodo, carteira atômica, ledger-live) sugerem que o atacante colete chaves de criptomoedas, não apenas tokens.

Carga útil do estágio 2

A busca por padrões Python codificados em hexadecimal no binário revelou uma sequência contínua de caracteres hexadecimais no deslocamento binário 1.709.372 (0x1A1F7C). A string começa com 78daab77f57163626464... - o byte mágico 78da é o cabeçalho de compressão zlib.

Decodificado e descompactado, ele produz um dropper Python 3 de 25 linhas:

O dropper usa soquetes # #AF_ALG ##, a interface do subsistema criptográfico do kernel Linux para entregar o código de shell do Stage 3. Este não é um soquete de rede convencional. O tráfego por meio de # #AF_ALG ## é invisível para as ferramentas padrão de monitoramento de rede. O shellcode é enviado em blocos de 4 bytes por meio de mensagens auxiliares # #sendmsg () ##, reduzindo ainda mais o sinal disponível para detectores de tempo de execução.

Carga útil LPE de estágio 3

A descompressão do blob zlib dentro do conta-gotas do Estágio 2 produz à carga do Estágio 3 um ELF independente da posição de 218 bytes:

A carga útil do estágio 3 é um código de shell de escalonamento mínimo de privilégios (218 bytes):

  • setuid (0): Chama sys_setuid (0) para reduzir o UID efetivo para 0 (root). Isso pressupõe que o binário esteja sendo executado com o conjunto de bits SUID (direcionamento). /usr/bin/su )
  • Execução do comando: recebe o comando para executar do estágio principal por meio do AF_ALG soquete e, em seguida, chama execve (“/bin/sh”, [” /bin/sh”, “-c”, cmd], NULL)
  • Saída normal: em qualquer erro, chama saída (0)

Este não é um exploit sofisticado do kernel, ele simplesmente explora o bit SUID em /usr/bin/su. Se o sistema tiver uma vulnerabilidade su binário, esse código de shell o aciona. Em um sistema corrigido, o shellcode falharia e sairia.

Persistência - O implante Systemd

Após o roubo de credenciais e a preparação da carga útil, o binário estabelece a persistência por meio de:

  • ~/.local/bin/systemd-broker ← cópia do binário principal
  • ~/.config/systemd/user/systemd-broker.service

O arquivo de serviço:

##loginctl enable-linger## é chamado para garantir que o serviço sobreviva à saída do usuário. ##reiniciar=sempre## garante que ele se recupere de mortes. O binário tem um timestamp para corresponder ao mtime de binários legítimos do sistema, reduzindo o sinal disponível para detectores baseados em sistemas de arquivos.

Saída Strace

PARA V2

1 cpur2zdsv762uzyoyzma6pvzz4a2xhv64zdouxpjlu3exyks7gh7leyd.cebola: 80

-> Usar o Tor como canal de comando e controle (C2) dá ao atacante anonimato e resiliência. Em vez de expor um IP ou domínio público que os defensores podem rastrear ou bloquear, o malware se conecta a um serviço oculto do Tor, cujo local real de hospedagem permanece oculto. Como ele incorpora o cliente Arti Tor legítimo, seu tráfego também se assemelha à atividade normal do Tor, em vez de um canal C2 de malware personalizado.

-> O Tor também oferece flexibilidade à infraestrutura do atacante. O endereço.onion de um serviço oculto está vinculado à sua identidade criptográfica, não ao IP do servidor de back-end. Desde que o invasor mantenha a chave privada, ele pode mover a infraestrutura C2 para novos hosts e, ao mesmo tempo, manter o mesmo endereço de cebola codificado, tornando a interrupção significativamente mais difícil.

Atribuição

Com base em informações obtidas de fontes subterrâneas, esta campanha foi vinculada ao ator da ameaça Sukob, supostamente um ex-membro do ecossistema de ransomware HellCat. Embora a evidência técnica nesta amostra não confirme de forma independente essa atribuição, a arte comercial se alinha com o perfil mais amplo.

Uma possibilidade interessante é a colaboração renovada entre Sukob e operadores associados a Equipe PCP. Historicamente, a equipe PCP tem sido associada a ataques agressivos de abuso da cadeia de suprimentos de software, como Shai Hulud vermes e relatórios clandestinos sugerem uma sobreposição entre alguns ex-membros afiliados ao Hellcat e esse ecossistema. O modelo de propagação semelhante a um worm nesta campanha, roubando credenciais de mantenedores e republicando silenciosamente pacotes trojanizados sob identidades confiáveis, se encaixa nesse padrão operacional. No momento, no entanto, essa continua sendo uma hipótese baseada na inteligência, em vez de uma atribuição tecnicamente comprovada.

Impacto e mitigações

Esta campanha tem como alvo sistemas de desenvolvedores Linux e ambientes de CI/CD nos quais as credenciais npm e GitHub estão presentes. Como o malware valida os tokens roubados e republica automaticamente os pacotes trojanizados em contas de mantenedores confiáveis, uma única máquina de desenvolvedor comprometida pode rapidamente se tornar um ponto de propagação da cadeia de suprimentos, afetando os usuários posteriores.

Embora a cebola C2 observada esteja atualmente offline, isso não deve ser considerado remediação. Como o malware usa um serviço oculto do Tor, o atacante pode reimplantar a infraestrutura enquanto mantém a mesma identidade de cebola. Os defensores devem priorizar:

  • Monitoramento de ganchos suspeitos de pré-instalação do npm ou execução inesperada de diretórios de projetos ocultos, como ./.claude/
  • Auditoria de publicações não autorizadas de pacotes, acesso a ~/.npmrc/~/.git-credentials e revogação imediata de tokens comprometidos
  • Alertas sobre atividades inesperadas do Tor/Arti ou persistência no nível do usuário por meio de serviços de usuário ~/.local/bin/ e systemd

Referências

CloudSEK TRIAD
CloudSEK Threat Research and Information Analytics Division
Nenhum item encontrado.

Blogs relacionados