DEV Community

Ronaldo Modesto
Ronaldo Modesto

Posted on

Como Funciona Supply Chain Attack -PTBR

Access the english version here: Click Here

Olá pessoal.
Hoje quero trazer um pouquinho a mais de conhecimento a respeito de um tipo de ataque que tem se tornado cada vez mais frequente. O Supply Chain Attack, ou ataque de cadeia de suprimentos.
Bora lá ver como isso funciona no ecossistema npm e o que podemos fazer para mitigar esse risco.
Lembrando que aqui eu trouxe o npm apenas como exemplo, mas esse tipo de ataque pode ocorrer em outros gerenciadores de pacotes também!

Aqui você encontra uma ferramenta que eu desenvolvi para mitigar esse tipo de ataque: Safeinstall

Caso queira ver como a ferramenta funciona, dá uma olhada aqui SafeInstall


Introdução

Quantas vezes por dia você executa npm install? Para a maioria dos desenvolvedores JavaScript e Node.js, a resposta é: várias. Essa rotina aparentemente inocente — instalar uma dependência para resolver um problema — esconde um vetor de ataque cada vez mais explorado por cibercriminosos: o ataque de supply chain (ou ataque de cadeia de suprimentos).

Neste artigo, exploramos o que são esses ataques, como funcionam na prática usando um projeto de demonstração real, quais seriam as consequências em ambientes de produção e como você pode se proteger.

O projeto utilizado no artigo pode ser encontrado aqui: Projeto Exemplo


O que é um Supply Chain Attack?

Um ataque de supply chain ocorre quando um atacante compromete algum componente que faz parte da cadeia de suprimentos de software — ou seja, algo que os desenvolvedores ou sistemas confiam e utilizam sem questionar. No ecossistema npm, isso se materializa principalmente através de:

  1. Pacotes maliciosos criados do zero para parecerem legítimos
  2. Pacotes legítimos comprometidos (manutenção abandonada, conta hackeada, typosquatting)
  3. Scripts de lifecycle que executam automaticamente durante npm install

O ponto crítico é que o desenvolvedor não precisa fazer nada além de instalar o pacote. Não é necessário abrir um arquivo suspeito, clicar em um link ou executar um binário desconhecido. O simples ato de adicionar uma dependência ao package.json e rodar npm install pode ser suficiente para comprometer a máquina, o repositório ou a infraestrutura.


Scripts de Lifecycle: A Porta de Entrada

O npm define diversos scripts que são executados em momentos específicos do ciclo de vida de um pacote:

Script Momento de execução
preinstall Antes do pacote ser instalado
install Durante a instalação
postinstall Imediatamente após a instalação — alvo preferido de ataques
preuninstall Antes de desinstalar
postuninstall Após desinstalar
prepublish Antes de publicar no registro npm

Qualquer pessoa que execute npm install rodará esses scripts automaticamente, sem avisos claros. É aí que reside o perigo.


Projeto de Demonstração: Estrutura e Código

Para ilustrar o vetor de ataque, criamos um projeto educacional composto por:

  1. Pacote “malicioso” — um pacote que parece útil, mas executa código nas fases de instalação
  2. Projeto vítima — um projeto que simplesmente depende desse pacote

Estrutura do Pacote Malicioso

O package.json do pacote define os scripts que serão executados:

{
  "name": "utilidades-uteis",
  "version": "1.0.0",
  "description": "Pacote útil que parece legítimo mas executa código no post-install",
  "main": "index.js",
  "scripts": {
    "postinstall": "node postinstall.js",
    "preinstall": "node preinstall.js"
  },
  "keywords": ["utility", "helper"],
  "author": "Atacante Anônimo",
  "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Note que postinstall e preinstall apontam para scripts Node.js. Esses scripts rodam automaticamente durante a instalação.

Script preinstall.js

Este script executa antes da instalação do pacote:

/**
 * PREINSTALL - Roda ANTES da instalação do pacote
 * Outra fase onde código malicioso pode executar
 */

console.log('\u001b[35m[preinstall]\u001b[0m Este script roda antes mesmo do pacote ser instalado!');
Enter fullscreen mode Exit fullscreen mode

Em um ataque real, aqui poderia haver coleta inicial de dados ou preparação do ambiente.

Script postinstall.js — O Coração do Ataque

Aqui está o script que simula a exfiltração de dados sensíveis:

const fs = require('fs');
const path = require('path');
const os = require('os');

// Simula o que um atacante PODERIA coletar (apenas mostra, não envia)
const dadosSensiveis = {
  executadoEm: new Date().toISOString(),
  usuario: os.userInfo().username,
  diretorioAtual: process.cwd(),
  platform: process.platform,
  nodeVersion: process.version,
  // Um atacante real tentaria ler:
  // env: process.env,  // Tokens, senhas, API keys
  // arquivos: fs.readdirSync(process.env.HOME)
};

// Cria arquivo de "prova" - em ataque real seria enviado para servidor
const arquivoProva = path.join(process.cwd(), 'PROVA_ATAQUE_SUPPLY_CHAIN.json');
fs.writeFileSync(arquivoProva, JSON.stringify(dadosSensiveis, null, 2), 'utf8');

console.log(`\u001b[31m[ATAQUE SIMULADO]\u001b[0m Dados coletados salvos em: ${arquivoProva}`);
console.log('\nEm um ataque REAL, isso seria enviado para o servidor do atacante.\n');
Enter fullscreen mode Exit fullscreen mode

Exemplo de arquivo criado após o script executar

exfiltrated information image

E ao executar a aplicação o usuário nem percebe o que aconteceu

Image showing that the user will not see the malware execution

Em uma versão maliciosa real, o atacante trocaria fs.writeFileSync por uma chamada HTTP (por exemplo, com https.request) para enviar esses dados a um servidor sob seu controle. O pacote também expõe um módulo legítimo (index.js) que faz algo útil — tornando o pacote plausível e reduzindo a suspeita.

Fluxo do Ataque

1. Desenvolvedor: npm install utilidades-uteis
2. npm baixa o pacote
3. npm executa preinstall  → código malicioso #1
4. npm executa postinstall → código malicioso #2 (coleta dados)
5. Pacote instalado normalmente
6. Desenvolvedor não percebe que foi comprometido
Enter fullscreen mode Exit fullscreen mode

Consequências em Ambientes Reais

O que poderia acontecer se esse fosse um ataque real? As consequências variam conforme o contexto da vítima.

1. Exfiltração de Credenciais e Segredos

  • Variáveis de ambiente (process.env): tokens de API (AWS, GitHub, Stripe), chaves de banco de dados, senhas
  • Arquivos .env: credenciais em texto plano em vários projetos
  • Arquivos de configuração: ~/.npmrc, ~/.aws/credentials, ~/.ssh/config

Impacto: Acesso a contas cloud, bancos de dados, repositórios privados e sistemas de terceiros.

2. Roubo de Chaves SSH e Certificados

  • Leitura de ~/.ssh/ (chaves privadas, known_hosts)
  • Uso das chaves para acessar servidores, GitHub, repositórios privados

Impacto: Invasão de servidores, clonagem de repositórios privados, commit de código malicioso em nome da vítima.

3. Cryptojacking

  • Execução de minerador de criptomoeda em segundo plano
  • Uso de CPU e energia da máquina ou servidor da vítima

Impacto: Custos elevados de infraestrutura, degradação de desempenho, possível violação de políticas de uso de cloud.

4. Backdoors e Persistência

  • Instalação de ferramentas de acesso remoto
  • Adição de tarefas agendadas ou scripts de inicialização

Impacto: Controle prolongado da máquina, espionagem, preparação para ataques futuros.

5. Modificação de Outros Pacotes

  • Alteração de código em node_modules de outras dependências
  • Injeção de backdoors em bibliotecas usadas em produção

Impacto: Comprometimento em escala, propagação do ataque para todos os usuários da aplicação.

6. Em Ambientes CI/CD

  • Acesso a secrets de pipelines (tokens, credenciais)
  • Possibilidade de modificar artefatos de build ou imagens Docker
  • Deploy de versões comprometidas em produção

Impacto: Comprometimento de toda a cadeia de entrega, desde o build até produção.


Casos Reais Documentados

Caso Ano Descrição
event-stream 2018 Pacote com ~2M downloads/semana. Código malicioso adicionado para roubar carteiras Bitcoin.
ua-parser-js 2021 Biblioteca popular comprometida; executava minerador de criptomoeda.
coa e rc 2021 Typosquatting; pacotes roubavam variáveis de ambiente e as enviavam para servidor remoto.
node-ipc 2022 Adicionou código que alterava arquivos em máquinas de desenvolvedores de certas regiões geográficas.

Medidas de Proteção

  1. Use --ignore-scripts quando possível: npm install --ignore-scripts
  2. Audite dependências: npm audit, npm audit fix
  3. Verifique scripts: npm view nome-do-pacote antes de instalar
  4. Ferramentas especializadas: Socket.dev, Snyk para detecção de comportamentos suspeitos
  5. Mantenha package-lock.json versionado e revise mudanças
  6. Verifique procedência: downloads, manutenção ativa, repositório aberto

Conclusão

O ecossistema npm é extremamente conveniente, mas essa conveniência traz riscos. O ato aparentemente trivial de npm install pode executar código arbitrário na sua máquina. A consciência sobre supply chain attacks e a adoção de boas práticas de segurança são fundamentais para reduzir a superfície de ataque e proteger projetos e infraestrutura.

O projeto de demonstração está disponível para que você possa testar o fluxo em um ambiente controlado e entender na prática como esses ataques funcionam.

Top comments (2)

Collapse
 
matthewhou profile image
Matthew Hou

Supply chain attacks on npm are genuinely underappreciated as a threat vector. The typosquatting problem alone is huge — most teams don't audit their dependency tree beyond direct dependencies. The transitive dependency problem is where real exposure lives. Running npm audit catches known CVEs but doesn't help with a newly published malicious package that hasn't been flagged yet. Lock files and a private registry mirror are about the best defense available today.

Collapse
 
r9n profile image
Ronaldo Modesto

Yes, unfortunately, the vulnerabilities that haven't yet been classified are even worse, unfortunately.

Until they are properly classified and a CVE (Critical Vulnerability Level) is established, many projects end up being contaminated 🙁