2026-03-30

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.
É um conjunto de 6 scripts de detecção que varrem repositórios procurando padrões maliciosos conhecidos. Cada scanner é especializado em um ecossistema:
| Scanner | Alvo |
|---|---|
scan-repo.sh | Verificações gerais (cross-language) |
scan-node.sh | Node.js / npm |
scan-php.sh | PHP (webshells, backdoors) |
scan-python.sh | Python / PyPI |
scan-go.sh | Go modules |
scan-polinrider.sh | Malware PolinRider (assinatura específica) |
Características:
[!] vermelho (alto risco), [~] amarelo (suspeito), [i] ciano (informativo)0 = limpo, 1 = achados, 2 = errogit clone https://github.com/lauralesteves/shady-project-scanner.git
cd shady-project-scanner
Pronto. Não precisa instalar nada.
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
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.
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).
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.
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ção – eval(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 perigosas – system/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 arquivos – file_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 PHP – php.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.
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 execution – subprocess 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ção – pickle.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.
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/exec – exec.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 CGo – import "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 tricks – go: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.
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.
Nunca clone direto na sua máquina. Use um ambiente isolado: VM, container ou instância EC2 descartável.
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.
Combine ferramentas. O Shady Project Scanner é baseado em padrões e complementa (não substitui) ferramentas como npm audit, pip-audit, Snyk ou Semgrep.
Desconfie de repos que pedem para desabilitar segurança. “Desabilite o antivírus antes de executar” é a red flag mais antiga que existe.
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.
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