Detectando malware em repositórios com Shady Project Scanner

2026-03-30

post-thumb

Índice

Você encontra um repositório no GitHub que promete ser um exploit PoC, uma ferramenta útil ou uma lib que resolve exatamente o seu problema. Clona, roda npm install e… parabéns, você acabou de instalar um stealer que está exfiltrando suas credenciais para um webhook do Discord.

Esse cenário não é ficção. Repositórios maliciosos são publicados diariamente disfarçados de ferramentas legítimas, exploits de segurança e utilitários open source. O problema é que, na maioria das vezes, o código malicioso está escondido atrás de ofuscação, hooks de instalação e payloads codificados em base64.

Para resolver isso, criei o Shady Project Scanner: uma suíte de scanners baseados em padrões que audita repositórios inteiros em busca de malware, backdoors e comportamentos suspeitos. Sem dependências externas, feito 100% em bash.


O que é o Shady Project Scanner

É um conjunto de 6 scripts de detecção que varrem repositórios procurando padrões maliciosos conhecidos. Cada scanner é especializado em um ecossistema:

ScannerAlvo
scan-repo.shVerificações gerais (cross-language)
scan-node.shNode.js / npm
scan-php.shPHP (webshells, backdoors)
scan-python.shPython / PyPI
scan-go.shGo modules
scan-polinrider.shMalware PolinRider (assinatura específica)

Características:

  • Zero dependências externas (bash + grep + find + awk)
  • Funciona em Linux e macOS
  • Severidade por cores: [!] vermelho (alto risco), [~] amarelo (suspeito), [i] ciano (informativo)
  • Códigos de saída: 0 = limpo, 1 = achados, 2 = erro

Instalação

git clone https://github.com/lauralesteves/shady-project-scanner.git
cd shady-project-scanner

Pronto. Não precisa instalar nada.


Como usar

O jeito mais simples é via Makefile. Para rodar todos os 6 scanners de uma vez:

make scan TARGET=/caminho/do/repositorio/suspeito

Para rodar um scanner específico:

make scan-node TARGET=/caminho/do/repositorio
make scan-python TARGET=/caminho/do/repositorio
make scan-repo TARGET=/caminho/do/repositorio

Ou diretamente:

./scanners/scan-repo.sh /caminho/do/repositorio
./scanners/scan-node.sh /caminho/do/repositorio

Exemplo real: escaneando um repositório suspeito

Vamos usar como alvo o repositório 0xgrama/StockX_PoC_1.07, que se apresenta como um exploit PoC para StockX. Repositórios como esse são o cenário clássico: prometem uma ferramenta ofensiva e o verdadeiro alvo é quem faz o download.

Aviso: Não clone esse repositório na sua máquina pessoal. Se quiser testar, use um ambiente isolado como uma VM ou uma instância EC2 descartável.

Depois de clonar o repositório suspeito em um ambiente seguro, basta apontar o scanner:

make scan TARGET=/caminho/para/StockX_PoC_1.07

O Shady Project Scanner vai executar, na sequência, os 6 scripts de detecção contra o repositório. Vamos ver o que cada um faz.


Os 6 scanners em detalhe

1. scan-repo.sh: verificações gerais (cross-language)

Esse é o scanner mais abrangente. Ele roda 14 verificações que se aplicam a qualquer linguagem:

Git Hooks maliciosos – Verifica se hooks em .git/hooks/ contêm comandos como curl, wget, bash, eval ou URLs de exfiltração (Discord webhooks, Slack, ngrok). Um post-checkout hook que baixa e executa um script remoto é um dos vetores de ataque mais comuns.

Crypto miners – Procura referências a xmrig, coinhive, pools de mineração (supportxmr, nanopool, f2pool) e endereços de carteiras Monero/Bitcoin.

Segredos e credenciais – Detecta chaves AWS (prefixo AKIA/ABIA/ACCA), chaves privadas, tokens do GitHub/Slack/JWT, strings de conexão com banco de dados contendo senhas, e arquivos sensíveis como .env, .npmrc, .pypirc, .pem, id_rsa.

Tampering em CI/CD – Verifica GitHub Actions pinados em branches ao invés de SHA, pull_request_target com acesso a secrets, curl | bash em workflows e permissões de escrita.

Docker abuse – Detecta containers privilegiados, montagem de paths sensíveis (/etc/shadow, ~/.ssh, ~/.aws, /var/run/docker.sock) e downloads de scripts remotos em Dockerfiles.

Ataques Unicode/Homoglyph – Procura caracteres de Trojan Source (CVE-2021-42574), como overrides bidirecionais (U+202A-E) e zero-width chars (U+200B-D), que podem esconder código malicioso visualmente.

Binários suspeitos – Flagga .exe, .dll, .so, .dylib, .bat, .ps1 e outros executáveis. Scripts PowerShell e batch com padrões perigosos recebem atenção especial.

Build scripts – Analisa Makefiles e shell scripts em busca de curl | bash, base64 --decode | exec, reverse shells (/dev/tcp, mkfifo, nc) e modificações em arquivos do sistema.

Blobs codificados grandes – Detecta linhas com mais de 2000 caracteres em arquivos fonte, indicando código minificado ou ofuscado embutido (exclui *.min.js e bundles legítimos).

Cron/Tarefas agendadas – Verifica arquivos cron com comandos de rede ou script (curl, wget, python, nc).

Configuração de IDE – Detecta tasks do VS Code com execução de shell e recomendações de extensões que podem ser maliciosas.

Abuso de Git config – Procura filter drivers customizados em .gitattributes (podem executar código silenciosamente), overrides de .gitconfig local e FUNDING.yml com carteiras suspeitas.

Reverse shells – Detecta padrões de reverse shell em bash (/dev/tcp), Python (socket), PHP (fsockopen) e Perl (IO::Socket).

Endpoints hardcoded – Encontra IPs não-privados com porta em scripts de build e config, excluindo ranges privados (127.0.0.1, 192.168.x.x, 10.x.x.x).


2. scan-node.sh: Node.js / npm

Focado em ameaças específicas do ecossistema JavaScript. 8 verificações:

Install hooks no package.json – Verifica se preinstall, postinstall ou preuninstall contêm curl, wget, eval, base64 ou node -e. Também detecta dependências com nomes de typosquatting conhecidos (lodash vs 1odash, event-stream, flatmap-stream, ua-parser-js) e bundledDependencies suspeitas.

Abuso de eval() / Function() – Detecta eval() com argumentos dinâmicos, new Function(), eval(atob(...)), eval(Buffer.from(...)) e o padrão mais perigoso: eval(response.data) ou eval(res.body), que é fetch-then-eval (execução remota de código).

child_process / execução de shell – Encontra execSync, exec, spawnSync com comandos suspeitos, require('child_process') ofuscado e require dinâmico com concatenação de strings.

Exfiltração de dados – Detecta leitura de process.env + requisições HTTP, acesso a arquivos sensíveis (.ssh, .aws, .npmrc), URLs de exfiltração (Discord, Slack, ngrok, webhook.site, pipedream, requestbin) e roubo de tokens de CI/CD (GITHUB_TOKEN, NPM_TOKEN, AWS_SECRET_ACCESS_KEY).

Payloads ofuscados – Strings Base64 longas (>100 chars), padrões hex-encoded (\x em massa), Unicode escapes, Buffer.from + base64 + eval/exec, padrões de javascript-obfuscator (variáveis _0x) e ofuscação estilo JSFuck.

Config npm/yarn – Registries customizados apontando para fora do npm oficial e tokens de autenticação em .npmrc/.yarnrc.

Integridade do lockfile – Verifica se URLs em package-lock.json apontam para fora dos registries oficiais (npmjs.org, yarnpkg.com) ou se tarballs vêm de locais não-padrão.

Native addons – Detecta arquivos binding.gyp e binários .node fora de node_modules.


3. scan-php.sh: PHP webshells e backdoors

Scanner especializado em webshells, backdoors e código ofuscado em PHP. 9 verificações:

Assinaturas de webshell – Detecta shells conhecidos (c99shell, r57shell, b374k, WSO, FilesMan, Ani-Shell, ALFA Shell, Weevely, p0wny, phpspy). Também detecta o padrão mais comum de webshell: $_GET/$_POST/$_REQUEST/$_COOKIE passados diretamente para funções perigosas (eval, system, exec, passthru, shell_exec, popen, proc_open). Identifica file_get_contents + eval (fetch-then-eval), php://input + execução de código e hashes MD5 hardcoded (senhas de backdoor).

Cadeias de ofuscaçãoeval(base64_decode(...)), eval(gzinflate(...)), eval(str_rot13(...)), cadeias aninhadas de decode, assert() com input codificado, preg_replace com modificador /e e create_function().

Funções perigosassystem/passthru/shell_exec com variáveis, operador backtick com interpolação, proc_open() e dl() (carregamento dinâmico de extensão).

Abuso de escrita de arquivosfile_put_contents com path controlado pelo usuário, fwrite com conteúdo decodificado e move_uploaded_file sem validação de MIME.

PHP escondido em arquivos não-PHP – Detecta código <?php dentro de arquivos .jpg, .png, .gif, .ico, .css, .txt, .html. Também flagga extensões duplas (.php.jpg) e extensões suspeitas (.phtml, .php5, .phar).

Payloads codificados – Strings Base64 muito longas (>200 chars), sequências hex longas (\x em massa), ofuscação com chr() (10+ caracteres encadeados), variáveis variáveis e concatenação de strings construindo nomes de funções.

Abuso de .htaccess – Injeção via auto_prepend_file/auto_append_file, AddHandler/AddType tornando imagens executáveis como PHP e diretivas SetHandler.

Config PHPphp.ini/.user.ini com auto_prepend_file e diretivas disable_functions.

Composer – Scripts suspeitos em hooks de instalação (post-install-cmd, post-update-cmd) contendo curl, wget, bash, eval ou base64.


4. scan-python.sh: Python / PyPI

Focado em ameaças do ecossistema Python. 8 verificações:

setup.py malicioso – Detecta imports de módulos suspeitos durante setup (subprocess, os.system, socket, urllib, requests), chamadas a exec/eval/compile, decodificação base64, classes de instalação customizadas com execução de código e fetch de URLs durante pip install.

Abuso de exec() / eval()exec/eval com payloads codificados (base64, codecs, zlib, marshal, bytes.fromhex), exec(compile(...)) e o padrão mais crítico: requests.get + exec ou urllib response + eval (fetch-then-exec). Também detecta cadeias multi-layer: base64 -> zlib -> marshal -> exec.

Payloads ofuscados – Strings Base64 longas (>200 chars), marshal.loads() (desserialização de bytecode), __import__ dinâmico, importlib.import_module com strings dinâmicas, bytes.fromhex + exec, chr() em massa, lambda wrapping exec(), getattr(__builtins__) e padrões de roubo de credenciais de navegador (Chrome, Firefox + sqlite3).

Exfiltração de dados – Leitura de arquivos sensíveis (.ssh, .aws, .env, /etc/passwd, /etc/shadow) + chamadas de rede, webhooks de exfiltração, coleta de os.environ + HTTP POST, DNS resolution + coleta de info do sistema e roubo de tokens.

subprocess / os command executionsubprocess com shell=True, os.system() com argumento variável, os.popen() e padrões de reverse shell (socket.connect + exec, pty.spawn).

Riscos de desserializaçãopickle.load(s) com dados não-confiáveis (HTTP, file open, stdin), yaml.load() sem SafeLoader e __reduce__ customizado com execução de comandos.

Arquivos de requirements – Dependências de URLs git (git+https://), URLs não-PyPI e indexes customizados (--index-url, --extra-index-url) apontando para fora de registries conhecidos.

Arquivos .pth suspeitos – Arquivos .pth com statements import (executam automaticamente ao iniciar o Python) e .egg-info com entry_points.


5. scan-go.sh: Go modules

Scanner para ataques de supply chain em projetos Go. 7 verificações:

Diretivas replace no go.mod – Detecta replace apontando para paths locais (../), repositórios não-padrão (fora de github.com, golang.org, google, gopkg.in), diretivas retract e dependências de domínios incomuns.

Funções init() suspeitas – Funções init() em arquivos que também importam net/http, net.Dial, os/exec, acessam variáveis de ambiente + fazem chamadas de rede, ou acessam paths sensíveis (.ssh, .aws, /etc/passwd).

Abuso de os/execexec.Command com interpretadores shell (bash, sh, powershell) + comandos suspeitos (curl, wget, nc, base64, whoami), fmt.Sprintf como argumento de exec (ofuscação) e exec.Command com os.Getenv (variável de ambiente como comando).

Exfiltração de dados – URLs de webhook/exfiltração, coleta de info do sistema (os.Hostname, runtime.GOOS) + HTTP POST, leitura de arquivos sensíveis, conexões TCP/UDP raw + exec (possível C2) e IPs hardcoded.

Abuso de CGoimport "C" com funções C perigosas (system(), popen(), execl/execv/execvp(), fork(), dlopen()).

Diretivas go:generate – Comandos generate suspeitos (curl, wget, bash, powershell, rm, nc, python) e fetch de URLs remotas.

Build constraints e embed tricksgo:embed com arquivos executáveis/ocultos (.sh, .bat, .exe, .dll, .so), //go:build ignore com código de exec/rede, go:linkname e chamadas a syscall.Exec/ForkExec/StartProcess.


6. scan-polinrider.sh: malware PolinRider

Scanner com assinatura específica para o malware PolinRider, que injeta payloads JS ofuscados em arquivos de configuração de projetos e faz force-push via batch scripts. 4 verificações:

Assinatura primária – Procura o payload ofuscado ("rmcej%otb%",2857687) em arquivos como postcss.config.mjs, tailwind.config.js, eslint.config.mjs, next.config.mjs e babel.config.js.

Assinatura secundária – Detecta o padrão global['!']='8-270-2';var _$_1e42=. Com a flag --js-all, varre todos os arquivos .js além dos configs conhecidos.

Scripts de propagação – Procura temp_auto_push.bat (script de force-push) e config.bat (orquestrador).

Artefatos Git – Detecta entradas de config.bat no .gitignore e commits amendados no git reflog, comportamento consistente com a propagação do PolinRider.

Aceita flags extras: --verbose para output detalhado e --js-all para varrer todos os .js.


Boas práticas ao analisar repositórios suspeitos

  1. Nunca clone direto na sua máquina. Use um ambiente isolado: VM, container ou instância EC2 descartável.

  2. Nunca rode npm install, pip install ou go build antes de escanear. Hooks de instalação são o vetor de ataque #1. Clone e escaneie antes de qualquer coisa.

  3. Combine ferramentas. O Shady Project Scanner é baseado em padrões e complementa (não substitui) ferramentas como npm audit, pip-audit, Snyk ou Semgrep.

  4. Desconfie de repos que pedem para desabilitar segurança. “Desabilite o antivírus antes de executar” é a red flag mais antiga que existe.

  5. Verifique a conta do autor. Conta nova, sem histórico, sem contribuições para outros projetos? O repo provavelmente não é o que promete ser.


Resumo

O Shady Project Scanner é uma ferramenta leve e sem dependências que roda mais de 50 verificações em 6 ecossistemas diferentes, cobrindo desde webshells PHP até supply chain attacks em Go modules. Não é bala de prata, mas é uma primeira linha de defesa rápida e eficiente antes de executar qualquer código de terceiros.

Se você trabalha com segurança, faz CTF ou simplesmente quer parar de confiar cegamente em npm install, dá uma olhada no projeto e contribua.

git clone https://github.com/lauralesteves/shady-project-scanner.git
cd shady-project-scanner
make scan TARGET=/caminho/do/repo/suspeito