Pacotes maliciosos no npm burlam defesas e afetam milhões

Escrito por
Jardeson Márcio
Jardeson Márcio é Jornalista e Mestre em Tecnologia Agroalimentar pela Universidade Federal da Paraíba. Com 8 anos de experiência escrevendo no SempreUpdate, Jardeson é um especialista...

Malware no npm burla travas de instalação e afeta milhões de projetos Node.js.

Pacotes maliciosos no npm estão adotando uma nova estratégia para escapar das barreiras de segurança introduzidas nas versões recentes do gerenciador de pacotes. Em vez de executar código durante a instalação, uma campanha descoberta pela Checkmarx esconde a carga maliciosa dentro do próprio código JavaScript das bibliotecas, fazendo com que o ataque seja ativado somente quando a aplicação utiliza determinadas funções.

O principal caso analisado é o indexed-btree, um pacote que imita a biblioteca legítima sorted-btree. Segundo a investigação, o pacote chegou a registrar quase 2 milhões de downloads semanais, mostrando que a redução dos riscos associados aos scripts de instalação não elimina o problema da cadeia de suprimentos do npm.

A campanha chama atenção porque combina engenharia social, ofuscação de código, exfiltração de informações por Slack e Telegram e blockchain como infraestrutura de comando e controle (C2). O caso também demonstra por que a análise de segurança precisa acompanhar o comportamento de uma dependência durante sua execução, e não apenas verificar o que acontece no momento da instalação.

Como os pacotes maliciosos no npm contornaram as defesas do npm v12

O npm v12 introduziu mecanismos mais rígidos para controlar scripts executados durante a instalação de dependências. A configuração allowScripts, por exemplo, permite estabelecer quais pacotes podem executar scripts de ciclo de vida, enquanto strict-allow-scripts pode transformar dependências não autorizadas em erros durante a instalação.

Tradicionalmente, um pacote comprometido poderia colocar sua carga em preinstall, install ou postinstall. Esses mecanismos são especialmente atraentes para atacantes porque permitem executar comandos automaticamente quando uma dependência é instalada.

O problema é que essa proteção considera principalmente o momento da instalação. Um pacote não precisa necessariamente executar código malicioso nessa etapa para representar risco.

Foi exatamente essa mudança de estratégia que a campanha explorou. O indexed-btree não dependia de um script de instalação malicioso. Em vez disso, o código perigoso foi incorporado à lógica normal da biblioteca e aguardava a utilização do pacote pela aplicação.

Imagem malware BeaverTail em pacotes npm

O gatilho de execução oculta no método BTree.prototype.set()

A carga maliciosa foi escondida no método BTree.prototype.set(), uma função pertencente à implementação da estrutura de dados oferecida pelo pacote.

De acordo com a análise da Checkmarx, a função verifica determinadas condições e, quando o gatilho é alcançado, executa o arquivo sharedLoad.min.js, que contém a primeira etapa do malware. A execução ocorre por meio de um processo separado do Node.js, permitindo que a atividade maliciosa fique ainda mais distante do fluxo convencional de instalação.

Esse detalhe é fundamental para compreender a evolução dos pacotes maliciosos no npm. Uma ferramenta que procura exclusivamente por postinstall pode concluir que determinada dependência não apresenta comportamento suspeito, enquanto o código perigoso permanece escondido em uma função aparentemente legítima.

Na prática, o pacote pode ser instalado sem produzir um alerta relacionado a scripts de ciclo de vida. O problema aparece posteriormente, quando o desenvolvedor ou a aplicação começa efetivamente a utilizar a biblioteca.

A técnica também dificulta determinadas formas de análise estática, especialmente quando combinada com ofuscação, arrays de strings codificadas e mecanismos de verificação de integridade.

Exfiltração de dados e uso de blockchain como C2

Depois de ativado, o malware coleta informações do ambiente comprometido. Entre os dados observados estão características do sistema operacional, arquitetura, nome do host, informações de CPU, memória e tempo de atividade.

Essas informações são enviadas para infraestrutura controlada pelos atacantes utilizando Slack e Telegram, transformando serviços legítimos de comunicação em canais para exfiltração.

O aspecto mais incomum está na utilização da rede de testes Ethereum Sepolia como parte da infraestrutura de comando e controle. Em vez de depender exclusivamente de um domínio ou endereço IP tradicional, o malware consulta um contrato inteligente para obter informações necessárias à operação da carga.

A investigação identificou um mecanismo criptográfico envolvendo X25519 e AES. O carregador gera um par de chaves X25519, obtém informações criptográficas disponibilizadas pelo contrato e calcula um segredo compartilhado. Esse processo é utilizado para derivar uma chave AES capaz de descriptografar partes da segunda etapa do malware armazenadas na blockchain.

A abordagem cria uma infraestrutura mais difícil de bloquear por métodos tradicionais. Mesmo que um endereço ou servidor seja removido, o contrato pode funcionar como um mecanismo para apontar os operadores para uma nova localização.

A Checkmarx também identificou recursos destinados à limpeza de rastros, incluindo mecanismos capazes de remover arquivos do malware e alterar novamente o código que serviu como gatilho.

Redes de pacotes falsificados e o impacto na comunidade

O ataque não dependeu somente de código malicioso. A campanha também utilizou elementos para criar uma aparência de legitimidade.

O indexed-btree foi apresentado com um nome próximo ao projeto legítimo sorted-btree, explorando uma técnica conhecida como typosquatting ou abuso de similaridade de nomes.

Além disso, os pesquisadores encontraram um repositório no GitHub associado ao pacote com atividade e commits que aparentavam construir um histórico legítimo de desenvolvimento. A própria presença de um repositório com vários commits pode aumentar a confiança de quem procura informações sobre uma biblioteca antes de adicioná-la a um projeto.

A campanha também envolveu outros nove pacotes que foram posteriormente removidos. São eles:

  • ordered-kv-index, com 448.184 downloads;
  • btree-leaderboard, com 493.685 downloads;
  • priority-slot-queue, com 402.860 downloads;
  • btree-range-store, com 468.092 downloads;
  • btree-core, com 1.951.274 downloads;
  • btree-time-index, com 425.312 downloads;
  • btree-lru-cache, com 372.185 downloads;
  • neighbor-key-map, com 366.019 downloads;
  • sliding-score-window, com 448.024 downloads.

Somados, esses nove pacotes ultrapassam 5,37 milhões de downloads registrados. O indexed-btree, por sua vez, chegou sozinho a quase 2 milhões de downloads semanais, segundo a pesquisa.

A infraestrutura também não parece ser totalmente isolada. A Checkmarx afirma ter encontrado o mesmo contrato inteligente associado anteriormente a outro pacote, chamado mutex-forge, indicando que a infraestrutura pode ter sido reutilizada em diferentes componentes da campanha.

O episódio reforça uma característica importante dos ataques à cadeia de suprimentos: popularidade não equivale a segurança. Uma dependência pode acumular centenas de milhares ou milhões de downloads e ainda assim ser comprometida ou criada especificamente para atingir desenvolvedores.

O que os desenvolvedores devem fazer para se proteger

A principal lição dessa campanha é que bloquear scripts de instalação continua sendo importante, mas não é suficiente. O próprio npm oferece controles para restringir scripts de ciclo de vida, incluindo allowScripts, strict-allow-scripts e ignore-scripts.

O problema é que essas medidas não impedem que uma biblioteca maliciosa execute código quando sua própria API é utilizada. Por isso, projetos que lidam com dependências de terceiros precisam combinar proteção durante a instalação com análise estática, monitoramento de comportamento em tempo de execução, revisão de dependências e controle de integridade.

Desenvolvedores e equipes de DevOps devem verificar imediatamente os arquivos package-lock.json e os manifests dos projetos para identificar a presença dos pacotes afetados. Também é importante revisar versões instaladas e dependências transitivas, já que uma biblioteca comprometida pode chegar ao ambiente sem ter sido adicionada diretamente pelo desenvolvedor.

Quem instalou ou executou algum dos pacotes envolvidos deve tratar o ambiente como potencialmente comprometido. Dependendo do contexto, isso inclui rotacionar chaves de API, tokens, credenciais e outros segredos acessíveis pelo processo Node.js, além de investigar conexões de rede e atividades anômalas.

O caso do indexed-btree mostra uma mudança relevante no comportamento dos pacotes maliciosos no npm: quando uma defesa fecha uma porta conhecida, os atacantes podem simplesmente deslocar a execução para outra etapa do ciclo de vida da aplicação.

Para a comunidade JavaScript e Node.js, isso significa que a segurança da cadeia de suprimentos não termina quando o npm install é concluído. O código de uma dependência precisa ser tratado como código executável durante toda a vida da aplicação.

Se sua equipe utiliza o ecossistema npm em produção, vale revisar agora as dependências afetadas, verificar os bloqueios de scripts configurados no npm v12 e compartilhar este alerta com desenvolvedores, equipes de segurança e profissionais de DevOps. A prevenção depende cada vez mais de saber o que um pacote faz quando é executado, e não apenas do que ele faz enquanto está sendo instalado.

Compartilhe este artigo
Jardeson Márcio é Jornalista e Mestre em Tecnologia Agroalimentar pela Universidade Federal da Paraíba. Com 8 anos de experiência escrevendo no SempreUpdate, Jardeson é um especialista em Android, Apple, Cibersegurança e diversos outros temas do universo tecnológico. Seu foco é trazer análises aprofundadas, notícias e guias práticos sobre segurança digital, mobilidade, sistemas operacionais e as últimas inovações que moldam o cenário da tecnologia.