
PhishCollector é um framework de pesquisa para coletar, analisar e rastrear sites de phishing.
PhishCollector é um framework de pesquisa para coletar, analisar e rastrear sites de phishing. Ele é propositadamente projetado como um ponto de partida — as regras de detecção, assinaturas de tecnologia, listas de palavras e plugins são todas estruturas de dados simples que os pesquisadores devem ler, estender e adaptar ao seu próprio cenário de ameaças.
Envie uma URL suspeita e o PhishCollector irá:
Todos os resultados são acessíveis via uma API REST, um painel web e uma CLI.


cp .env.example .env # configure (veja abaixo)
docker compose up --build # inicia db + app + frontend
| Serviço | URL |
|---|---|
| GUI | http://localhost:3000 |
| Documentação da API | http://localhost:8000/docs |
| BD | localhost:5432 |
Todas as configurações são variáveis de ambiente com o prefixo PHISH_. Copie .env.example para .env e ajuste.
Roteando todo o tráfego de saída através de um proxy mantém o IP do analista oculto do servidor de phishing.
PHISH_PROXY_URL=socks5://127.0.0.1:9050
PHISH_PROXY_SSL_VERIFY=true # Tor não intercepta TLS
O Burp atua como um intermediário TLS e apresenta seu próprio certificado CA para cada conexão HTTPS. Sem desabilitar a verificação SSL, toda requisição HTTPS através do proxy falhará.
PHISH_PROXY_URL=http://127.0.0.1:8080
PHISH_PROXY_SSL_VERIFY=false # necessário para Burp / proxies interceptadores
Nota:
PHISH_PROXY_SSL_VERIFY=falseafeta apenas as conexões HTTPS de saída feitas pelo backend Python (plugins, fingerprinter, spider). O navegador Playwright já opera comignore_https_errors=trueindependentemente desta configuração.
Aviso: Nunca defina
PHISH_PROXY_SSL_VERIFY=falsesem um proxy configurado — isso desabilitaria a validação de certificado para todas as chamadas de API externas (URLhaus, VirusTotal).
Caminho base: /api/v1
Documentação interativa completa em /docs (Swagger UI).
curl -X POST http://localhost:8000/api/v1/collections \
-H 'Content-Type: application/json' \
-d '{"url": "https://suspicious-site.example.com", "use_wordlist": true}'
# Instalar (dentro do container ou venv local com requirements.txt)
pip install -e .
# Enviar uma URL e aguardar conclusão
phishcollector collect https://target.example.com --wait
# Com fuzzing de wordlist
phishcollector collect https://target.example.com --wordlist --wait
# Listar jobs recentes
phishcollector list
# Ver detalhe completo
phishcollector detail <job-id>
# Baixar screenshot
phishcollector screenshot <job-id> -o capture.png
# Buscar por stack tecnológico / hash de favicon / país
phishcollector search --tech WordPress --country RU
phishcollector search --favicon-hash -1234567890
Requer uma Auth-Key gratuita de auth.abuse.ch.
PHISH_URLHAUS_ENABLED=true
PHISH_URLHAUS_API_KEY=<sua-chave-de-autenticação>
Requer uma chave de API gratuita ou paga de virustotal.com.
PHISH_VIRUSTOTAL_API_KEY=<sua-chave>
Quando uma URL ainda não foi analisada pelo VT, o PhishCollector a envia para varredura e automaticamente busca novamente o resultado a cada 30 segundos até que seja resolvido.
Cada plugin é um único arquivo em phishcollector/plugins/ que expõe uma função assíncrona:
# phishcollector/plugins/myplugin.py
from . import CheckResult
async def check(url: str, proxy_url=None, ssl_verify=True) -> CheckResult:
# consulte seu feed / API aqui
return CheckResult(
plugin_name="myplugin",
status="malicious", # malicious | suspicious | clean | unknown | error
score=0.95, # 0.0–1.0, ou None
result={"raw": ...}, # armazenado como JSONB, exibido na GUI
)
Em seguida, registre-o em phishcollector/plugins/runner.py:
from .myplugin import check as myplugin_check
tasks.append(myplugin_check(url, proxy_url=settings.proxy_url, ssl_verify=settings.proxy_ssl_verify))
Nenhuma outra alteração é necessária — o resultado é automaticamente armazenado, exibido no painel e considerado na pontuação de ameaça.
O mecanismo de detecção é intencionalmente mantido como dados simples e legíveis para que os pesquisadores possam ajustá-lo aos kits e campanhas que estão rastreando. Tudo reside em um único arquivo:
phishcollector/collector/fingerprint.py
PHISHING_PATTERNS — regras regex verificadas contra HTML + JS renderizadosCada entrada é uma tupla (regex, rótulo legível) agrupada em categorias. Uma correspondência em qualquer categoria é exibida na aba Indicadores e conta para a pontuação de ameaça.
PHISHING_PATTERNS: dict[str, list[tuple[str, str]]] = {
"credential_harvest": [
(r"document\.getElementById\(['\"]password['\"]", "JS lê campo de senha por ID"),
(r"btoa\s*\(.*password", "Codificando senha em Base64"),
# adicione suas próprias regras aqui …
],
"obfuscation": [
(r"\beval\s*\(", "Uso de eval()"),
(r"atob\s*\(", "Decodificação Base64 em tempo de execução"),
],
"exfiltration": [
(r"api\.telegram\.org/bot", "Exfiltração por bot do Telegram"),
(r"@(?:gmail|yahoo|hotmail|outlook)\.com", "Endereço de email gratuito em código"),
],
"antibot": [
(r"navigator\.webdriver", "Verificação de propriedade WebDriver"),
(r"ipqualityscore|ipqs\.com", "Serviço anti-bot IPQS"),
],
"kit_indicators": [
(r"office365|microsoft365", "Tema de phishing Office 365"),
(r"paypal.*limit|limit.*paypal", "Tema de limitação PayPal"),
# novo kit que você identificou? adicione uma regra aqui:
(r"docusign.*sign|e.?sign.*document", "Isca DocuSign"),
(r"(?:dhl|fedex|ups).*track", "Isca de entrega de encomenda"),
],
}
Para adicionar uma regra: anexe uma tupla à lista da categoria relevante. Para adicionar uma categoria: adicione uma nova chave — o nome da categoria aparece automaticamente como cabeçalho de seção na aba Indicadores.
# Exemplo: rastrear fingerprint de um kit recém-descoberto
"my_campaign_2024": [
(r"panel\.php\?cmd=send", "Caminho conhecido de painel C2"),
(r"X-Mailer:\s*PHPMailer\s*5\.2\.1", "Versão específica do PHPMailer usada pelo kit"),
],
TECH_SIGNATURES — detecção de tecnologiaAssinaturas verificadas contra HTML, cabeçalhos de resposta, cookies e a URL final. As tecnologias detectadas aparecem no painel Tecnologias e são pesquisáveis em todas as coleções.
TECH_SIGNATURES: dict[str, dict] = {
"WordPress": {
"html": [r"wp-content", r"wp-includes"],
"url": [r"/wp-login\.php"],
"cookies": ["wordpress_"],
},
# Adicione qualquer coisa que queira rastrear:
"GoPhish": {
"html": [r"rid=[a-zA-Z0-9]{20}"],
"url": [r"/track\?rid="],
},
"Evilginx": {
"url": [r"phishlets"],
"html": [r"__utmz.*evilginx"],
},
}
Cada chave de assinatura (o nome da tecnologia) se torna uma string pesquisável via GET /search?technology=GoPhish.
A wordlist padrão do spider está em wordlists/phishing_paths.txt — um caminho por linha, # para comentários. Contém caminhos comuns de kits de phishing (gate.php, send.php, result.php, painéis de admin, etc.). Adicione caminhos para kits que você encontra regularmente:
# Caminhos de kit recém-observados
/panel/send.php
/b374k.php
/uploads/gate.php
Content-Type: text/plain e Content-Disposition: attachment — o navegador o baixa em vez de renderizá-lo.hmac.compare_digest para evitar ataques de timing.X-Frame-Options: DENY e Referrer-Policy: no-referrer.Os artefatos são gravados no diretório PHISH_DATA_DIR (padrão /data, volume montado no Docker):
/data/
screenshots/ <id-da-coleção>.png
html/ <id-da-coleção>.html
assets/
<id-da-coleção>/
<prefixo-sha256>.js
<prefixo-sha256>.css
Todo o resto (fingerprints, logs HTTP, resultados do spider, resultados de plugins, tags, notas) reside no PostgreSQL.
phishcollector/
collector/
browser.py # Captura Playwright, JS furtivo, rotação de UA
fingerprint.py # Todos os probes de fingerprint + PHISHING_PATTERNS + TECH_SIGNATURES
spider.py # Extração de links, robots.txt, sitemap, fuzzing de wordlist
orchestrator.py # Ciclo de vida do job: une todos os módulos
plugins/
__init__.py # Dataclass CheckResult
urlhaus.py # Plugin abuse.ch URLhaus
virustotal.py # Plugin VirusTotal v3
runner.py # Executa plugins habilitados concorrentemente
api/
routes.py # Endpoints FastAPI
main.py # Ponto de entrada da aplicação, CORS, middleware de autenticação
models.py # Modelos ORM SQLAlchemy
config.py # Configurações Pydantic (variáveis de ambiente)
database.py # Engine, fábrica de sessões, migrações de esquema
frontend/
app.js # SPA em Vanilla JS
style.css # UI terminal cyber
nginx.conf # Proxy reverso + cabeçalhos de segurança
wordlists/
phishing_paths.txt # Wordlist padrão do spider
# Iniciar apenas o banco de dados
docker compose up db -d
# Executar a API localmente
pip install -r requirements.txt
playwright install chromium
uvicorn phishcollector.main:app --reload
# Executar testes (se houver)
pytest
| Variável | Padrão | Descrição |
|---|
PHISH_DATABASE_URL | postgres://… | DSN do PostgreSQL |
PHISH_API_KEY | (vazio) | Se definido, todas as requisições exigem X-API-Key: <valor> |
PHISH_DATA_DIR | /data | Raiz de armazenamento para screenshots, HTML, ativos |
PHISH_BROWSER_TIMEOUT | 30000 | Timeout de carregamento de página em ms |
PHISH_REQUEST_TIMEOUT | 15 | Timeout de sub-requisição HTTP em segundos |
PHISH_MAX_SPIDER_PAGES | 50 | Máximo de URLs que o spider visita por job |
PHISH_MAX_ASSET_SIZE | 10485760 | Tamanho máximo de arquivo JS/CSS a armazenar (bytes) |
PHISH_PROXY_URL | (vazio) | Proxy de saída — veja abaixo |
PHISH_PROXY_SSL_VERIFY | true | Defina false para proxies interceptadores — veja abaixo |
PHISH_URLHAUS_ENABLED | false | Habilita verificação de reputação URLhaus |
PHISH_VIRUSTOTAL_API_KEY | (vazio) | Chave de API do VirusTotal v3 (deixe vazio para desabilitar) |
| Método | Caminho | Descrição |
|---|
POST | /collections | Enviar uma URL para coleta |
GET | /collections | Listar todas as coleções |
GET | /collections/{id} | Detalhe completo + fingerprint |
GET | /collections/{id}/screenshot | PNG da página inteira |
GET | /collections/{id}/html | HTML capturado (baixado como texto simples) |
GET | /collections/{id}/requests | Log de requisições de rede |
GET | /collections/{id}/spider | Resultados do spider |
GET | /collections/{id}/plugins | Resultados dos plugins de inteligência de ameaças |
POST | /collections/{id}/plugins/refresh | Reexecutar plugins (ex.: buscar resultado pendente do VT) |
POST | /collections/{id}/rescan | Recoletar a mesma URL (o original é preservado) |
PATCH | /collections/{id} | Atualizar tags e notas |
GET | /collections/{id}/export?format=json|csv | Exportar dados da coleção |
DELETE | /collections/{id} | Deletar uma coleção e todos os seus artefatos |
GET | /search | Buscar fingerprints por IP, hash de favicon, tecnologia, país, título |