NPM é inundado por pacotes maliciosos baixados mais de 86 mil vezes
(arstechnica.com)- Foi confirmado que mais de 100 pacotes maliciosos voltados ao roubo de credenciais foram enviados ao repositório NPM sem serem detectados desde agosto, somando mais de 86 mil downloads
- A empresa de segurança Koi informou que uma campanha de ataque batizada de “PhantomRaven” distribuiu 126 pacotes maliciosos explorando o recurso Remote Dynamic Dependencies (RDD) do NPM
- O RDD é uma estrutura que permite que pacotes baixem dinamicamente código de dependências a partir de domínios não confiáveis, o que impede a detecção por ferramentas de análise estática
- Os invasores usaram esse recurso para baixar código malicioso por conexões HTTP, enquanto os metadados dos pacotes exibiam “0 Dependencies”, fazendo com que desenvolvedores e scanners de segurança não percebessem o problema
- Essa vulnerabilidade estrutural expõe os limites da gestão de segurança do ecossistema NPM e os riscos do mecanismo de instalação automática
Disseminação de pacotes maliciosos no repositório NPM
- Invasores aproveitaram uma fraqueza estrutural do repositório de código do NPM para enviar, desde agosto, mais de 100 pacotes voltados ao roubo de credenciais
- A maioria dos pacotes foi distribuída sem detecção, e o total acumulado de downloads passou de 86 mil
- A empresa de segurança Koi deu a esse ataque o nome de campanha PhantomRaven e analisou que um recurso específico do NPM foi explorado
- Segundo a Koi, cerca de 80 dos 126 pacotes maliciosos ainda permaneciam no NPM no momento da publicação da matéria
Estrutura vulnerável do Remote Dynamic Dependencies (RDD)
- O RDD é um recurso que permite que pacotes baixem dinamicamente código de dependências de sites externos
- Normalmente, as dependências são baixadas da infraestrutura confiável do NPM, mas o RDD também permite downloads por conexões não criptografadas, como HTTP
- Os responsáveis pelo ataque PhantomRaven usaram esse recurso para configurar o download de código a partir de URLs maliciosas (ex.:
http://packages.storeartifact.com/npm/unused-imports)- Essas dependências ficam invisíveis para desenvolvedores e scanners de segurança e aparecem nas informações do pacote como “0 Dependencies”
- Por causa do recurso de instalação automática do NPM, esse código de dependência “invisível” é executado automaticamente
Limites de detecção das ferramentas de segurança
- Oren Yomtov, da Koi, afirmou que “o PhantomRaven é um caso de exploração sofisticada de um ponto cego das ferramentas de segurança existentes”
- O RDD não é detectado por ferramentas de análise estática
- Com isso, os invasores conseguiram contornar a validação de segurança e distribuir código malicioso
Fatores adicionais de vulnerabilidade
- A Koi explicou que as dependências baixadas via RDD são baixadas novamente do servidor do invasor a cada instalação
- Como não há cache nem controle de versão, existe a possibilidade de que códigos maliciosos diferentes sejam injetados a cada instalação do mesmo pacote
- Essa estrutura de download dinâmico dificulta a verificação de integridade dos pacotes
Estrutura e contexto do NPM
- O NPM é um gerenciador de pacotes para JavaScript, administrado pela npm, Inc., subsidiária do GitHub
- É o gerenciador de pacotes padrão do Node.js e é composto pelo cliente de linha de comando e pelo npm registry
- O registry armazena pacotes públicos e privados pagos, que podem ser pesquisados pelo site
- O caso é apontado como um exemplo de como a estrutura de gerenciamento automático de dependências do NPM pode ser explorada em ataques
Outras menções
- No fim da matéria, é mencionada a opinião de que a execução desnecessária de JavaScript deve ser bloqueada
- No entanto, ressalta-se que este ataque é um caso em que até mesmo código JavaScript essencial foi explorado
2 comentários
Criei um script de scanner em tempo real.
No caminho do repositório suspeito,
npx sha1-hulud-scanneré só executar.
Código-fonte: https://github.com/developerjhp/sha1-hulud-scanner
Comentários do Hacker News
Ultimamente, coloquei um alias para executar o comando
npmdentro de um contêiner DockerAssim, ele não expõe minhas variáveis de ambiente, não acessa arquivos fora do diretório atual e também não consegue acessar arquivos de configuração como
.bashrcReferência: Run tools inside Docker
npmbaixa código arbitrário que vai ser executado logo em seguidaEm vez disso, recomendo
pnpm. Por padrão, ele não executa scripts de lifecycle, e você pode definir em whitelist quais scripts serão permitidosSe você quer proteção de verdade, precisa colocar em sandbox não só a instalação, mas toda a execução
Do jeito que está, bloquear apenas o post-install é só meia medida. Ataques à cadeia de suprimentos estão ficando cada vez mais perigosos
Se
neovimouvscodeforem comprometidos, já dá para fazer coisas bem perigosas com as permissões do usuárioUm alias simples funciona para
node/npm, mas é difícil aplicar isso a outros programas, porque é preciso montar no contêiner os recursos necessáriosEu me pergunto isso há muito tempo: por que as pessoas executam
npmno sistema como se fosse nada?Para quem está acostumado com builds reprodutíveis como
make, foi chocante ver onpmbaixar coisas diferentes e produzir resultados diferentes a cada vezAté gerar CSS preso a dependências do npm me parecia estranho. Então tentei congelar todo o ambiente npm dentro de Docker, mas no fim parece uma batalha perdida
maven,nuget,pip,npm, todos iguaisSe ainda dependêssemos de gerenciadores de pacotes de distribuições como antigamente, seria impossível ter um ecossistema rápido como o atual
Dito isso, estão surgindo novos gerenciadores de pacotes com segurança reforçada. Não é correto condenar o meio sem entender o motivo por trás dele
npmcom Docker, eu perguntaria se validava esse ambiente toda vez que atualizava as dependênciasNa prática,
npmepnpmjá fixam dependências por padrão com arquivos locknpm install thing” ser fácil e barato demaisMuito open source acaba cheio de código para currículo em vez de qualidade, e no fim vai parar em coisas como rastreadores de anúncios de grandes empresas ou apps de carteira
npm installnão apenas baixa pacotes, ele executa códigoOs hooks preinstall, install e postinstall do
package.jsonrealmente são executadosQual seria um motivo legítimo para precisar executar comandos arbitrários durante a instalação?
Relatório relacionado: PhantomRaven npm malware
Outro caso: blog da Socket.dev
Por exemplo, pacotes do kernel Linux executam scripts de post-install para regerar o initramfs e atualizar o GRUB
A maioria dos pacotes DEB/RPM inclui scripts assim. Ou seja, é um problema de projeto
npmqualquer um pode publicar pacotesDistribuições Linux têm um sistema confiável de mantenedores e às vezes constroem diretamente uma raiz de confiança baseada em PGP
Já
npm,pip,rubygems,cargoetc. são, na prática, só versões mais sofisticadas de “curl | bash”Esse tipo de build em post-install foi necessário para reduzir a carga de manutenção
Package.swiftMas ouvi dizer que ele é fortemente sandboxed, então é difícil abusar disso
Referência: documentação do SwiftPM, PackageDescription
pnpm v10desativa por padrão todos os scripts de lifecycle, e o usuário precisa liberá-los manualmenteDiscussão relacionada
Vendo os ataques recentes ao
npm, fico pensando se desenvolver comnpmainda é seguroToda vez que começo um projeto React, são instalados centenas de pacotes, e eu nem sei o que eles fazem
No backend eu instalo explicitamente só os pacotes necessários, mas no frontend parece uma caixa de Pandora de vulnerabilidades
npmé o maior e por isso aparece mais nas notíciasjjdo Rust e vieram 470 pacotes; no Python,wan2gpinstalou 211. No fim, é tudo a mesma coisaComo no caso do
xz, cada dependência fica nas mãos de pessoas aleatórias, e você precisa acreditar que elas não vão cair em engenharia socialPyPItambém não é seguro. Já houve casos de injeção de código malicioso em pacotes legítimos por meio de invasões no GitHub ActionsSempre fico apreensivo ao desenvolver com frameworks como Angular e Vue
Quando olho para milhares de dependências dentro de
node_modules, parece um prenúncio de desastreSe um único desenvolvedor de open source cair num phishing, tudo pode ser infectado na hora
O ecossistema JavaScript está quebrado na raiz. Um único erro de digitação já pode expor você a um ataque na cadeia de suprimentos
Em NuGet ou Maven isso também pode acontecer, mas lá a biblioteca padrão é maior, há menos dependências e existe mais sensação de controle
Não é perfeito, mas já é um passo melhor
Dessas 86.000 instalações, a maior parte provavelmente não veio de usuários reais, mas de scanners automatizados ou bots
Quando você publica uma versão nova, é comum ver centenas de downloads em um ou dois dias, mas talvez não sejam pessoas de verdade
Ou seja, pode ser que quase ninguém tenha sido infectado
Também há muitos ataques mirando nomes de pacotes alucinados por chatbots de IA. É mais do que simples estatística
Para uma explicação mais detalhada do ataque, veja a matéria da BleepingComputer
Fico curioso se existe alguma forma de detectar ou filtrar, durante o
npm install, pacotes que usam URLs HTTP como dependênciaComo é possível servir payloads diferentes para cada solicitante, scanners comuns têm dificuldade para detectar isso
Como desenvolvedor hobbyista, fico pensando em como me preparar para esse tipo de ataque à cadeia de suprimentos
Você segue um tutorial famoso, instala as dependências, e quando percebe já ficou relaxado com segurança
Também rodo vários serviços no meu homelab, então me preocupo com a possibilidade de algum bot invadir. Por onde começar?
Não é garantia perfeita, mas é muito melhor do que ter o servidor inteiro comprometido
Copiar só o código necessário e usar diretamente também pode ser uma boa forma de aprender e de aumentar a segurança
Numa estrutura dessas, é possível obter confiabilidade no nível da distribuição sem que milhões de usuários precisem validar tudo por conta própria
Ex.: Hono, Zod
Recentemente migrei para o Bun, que já traz embutidos itens como driver de banco de dados e cliente S3, reduzindo downloads adicionais
Uma estrutura que busca dependências em hooks de lifecycle sempre pode virar um ponto de virada para ataque
Mesmo que hoje esteja tudo normal, no futuro o dono pode ser hackeado ou mudar de ideia, e aquilo virar código malicioso
No fim, hooks de instalação desse tipo são um projeto insustentável