
PhishCollector — это исследовательская платформа для сбора, анализа и отслеживания фишинговых сайтов.
PhishCollector — это исследовательский фреймворк для сбора, анализа и отслеживания фишинговых сайтов. Он намеренно спроектирован как отправная точка — правила обнаружения, сигнатуры технологий, словари и плагины представляют собой простые структуры данных, которые исследователи могут читать, расширять и адаптировать под свой ландшафт угроз.
Отправьте подозрительный URL, и PhishCollector:
Все результаты доступны через REST API, веб-панель и CLI.


cp .env.example .env # настройте (см. ниже)
docker compose up --build # запускает db + app + frontend
| Сервис | URL |
|---|---|
| GUI | http://localhost:3000 |
| API docs | http://localhost:8000/docs |
| БД | localhost:5432 |
Все настройки задаются через переменные окружения с префиксом PHISH_. Скопируйте .env.example в .env и отредактируйте.
Маршрутизация всего исходящего трафика через прокси скрывает IP-адрес аналитика от фишингового сервера.
PHISH_PROXY_URL=socks5://127.0.0.1:9050
PHISH_PROXY_SSL_VERIFY=true # Tor не перехватывает TLS
Burp работает как TLS-посредник и подставляет собственный CA-сертификат для каждого HTTPS-соединения. Без отключения проверки SSL каждое HTTPS-соединение через прокси будет завершаться ошибкой.
PHISH_PROXY_URL=http://127.0.0.1:8080
PHISH_PROXY_SSL_VERIFY=false # обязательно для Burp / перехватывающих прокси
Примечание:
PHISH_PROXY_SSL_VERIFY=falseвлияет только на исходящие HTTPS-соединения Python-бэкенда (плагины, сборщик отпечатков, паук). Браузер Playwright всегда работает сignore_https_errors=trueнезависимо от этой настройки.
Предупреждение: Никогда не устанавливайте
PHISH_PROXY_SSL_VERIFY=falseбез настроенного прокси — это отключит проверку сертификатов для всех внешних API-вызовов (URLhaus, VirusTotal).
Базовый путь: /api/v1
Полная интерактивная документация по адресу /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}'
# Установка (внутри контейнера или локально в venv с requirements.txt)
pip install -e .
# Отправить URL и дождаться завершения
phishcollector collect https://target.example.com --wait
# С фаззингом по словарю
phishcollector collect https://target.example.com --wordlist --wait
# Список последних задач
phishcollector list
# Просмотр полной информации
phishcollector detail <job-id>
# Скачать скриншот
phishcollector screenshot <job-id> -o capture.png
# Поиск по технологическому стеку / хешу фавикона / стране
phishcollector search --tech WordPress --country RU
phishcollector search --favicon-hash -1234567890
Требуется бесплатный Auth-Key с auth.abuse.ch.
PHISH_URLHAUS_ENABLED=true
PHISH_URLHAUS_API_KEY=<ваш-auth-key>
Требуется бесплатный или платный API-ключ с virustotal.com.
PHISH_VIRUSTOTAL_API_KEY=<ваш-ключ>
Если URL ещё не был проанализирован VT, PhishCollector отправляет его на сканирование и автоматически повторно запрашивает результат каждые 30 секунд до получения ответа.
Каждый плагин — это отдельный файл в phishcollector/plugins/, который содержит одну асинхронную функцию:
# phishcollector/plugins/myplugin.py
from . import CheckResult
async def check(url: str, proxy_url=None, ssl_verify=True) -> CheckResult:
# запрос к вашему фиду / API
return CheckResult(
plugin_name="myplugin",
status="malicious", # malicious | suspicious | clean | unknown | error
score=0.95, # 0.0–1.0, или None
result={"raw": ...}, # сохраняется как JSONB, отображается в GUI
)
Затем зарегистрируйте его в 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))
Больше никаких изменений не требуется — результат автоматически сохраняется, отображается в панели управления и учитывается в оценке угрозы.
Движок обнаружения намеренно сделан в виде простых, читаемых данных, чтобы исследователи могли настраивать его под отслеживаемые наборы и кампании. Всё находится в одном файле:
phishcollector/collector/fingerprint.py
PHISHING_PATTERNS — правила регулярных выражений, проверяемые на отрендеренном HTML + JSКаждая запись — это кортеж (регулярное_выражение, человекочитаемая_метка), сгруппированный по категориям. Совпадение в любой категории отображается на вкладке Индикаторы и учитывается в оценке угрозы.
PHISHING_PATTERNS: dict[str, list[tuple[str, str]]] = {
"credential_harvest": [
(r"document\.getElementById\(['\"]password['\"]", "JS читает поле пароля по ID"),
(r"btoa\s*\(.*password", "Кодирование пароля в Base64"),
# добавьте свои правила здесь …
],
"obfuscation": [
(r"\beval\s*\(", "Использование eval()"),
(r"atob\s*\(", "Декодирование Base64 во время выполнения"),
],
"exfiltration": [
(r"api\.telegram\.org/bot", "Эксфильтрация через Telegram бота"),
(r"@(?:gmail|yahoo|hotmail|outlook)\.com", "Бесплатный email-адрес в коде"),
],
"antibot": [
(r"navigator\.webdriver", "Проверка свойства WebDriver"),
(r"ipqualityscore|ipqs\.com", "Антибот-сервис IPQS"),
],
"kit_indicators": [
(r"office365|microsoft365", "Тема фишинга Office 365"),
(r"paypal.*limit|limit.*paypal", "Тема ограничения PayPal"),
# заметили новый набор? добавьте правило сюда:
(r"docusign.*sign|e.?sign.*document", "Приманка DocuSign"),
(r"(?:dhl|fedex|ups).*track", "Приманка доставки посылок"),
],
}
Чтобы добавить правило: добавьте кортеж в соответствующий список категории. Чтобы добавить категорию: добавьте новый ключ — имя категории автоматически отобразится как заголовок раздела на вкладке Индикаторы.
# Пример: отслеживание отпечатка недавно обнаруженного набора
"my_campaign_2024": [
(r"panel\.php\?cmd=send", "Известный путь C2-панели"),
(r"X-Mailer:\s*PHPMailer\s*5\.2\.1", "Конкретная версия PHPMailer, используемая набором"),
],
TECH_SIGNATURES — обнаружение технологийСигнатуры сопоставляются с HTML, заголовками ответа, куками и конечным URL. Обнаруженные технологии отображаются на панели Технологии и доступны для поиска по всем коллекциям.
TECH_SIGNATURES: dict[str, dict] = {
"WordPress": {
"html": [r"wp-content", r"wp-includes"],
"url": [r"/wp-login\.php"],
"cookies": ["wordpress_"],
},
# Добавьте всё, что хотите отслеживать:
"GoPhish": {
"html": [r"rid=[a-zA-Z0-9]{20}"],
"url": [r"/track\?rid="],
},
"Evilginx": {
"url": [r"phishlets"],
"html": [r"__utmz.*evilginx"],
},
}
Каждый ключ сигнатуры (название технологии) становится строкой для поиска через GET /search?technology=GoPhish.
Словарь паука по умолчанию находится в wordlists/phishing_paths.txt — один путь на строку, # для комментариев. Он содержит типичные пути фишинговых наборов (gate.php, send.php, result.php, панели администратора и т.д.). Добавляйте пути для наборов, которые встречаете регулярно:
# Пути недавно замеченных наборов
/panel/send.php
/b374k.php
/uploads/gate.php
Content-Type: text/plain и Content-Disposition: attachment — браузер скачивает его, а не отображает.hmac.compare_digest для предотвращения атак по времени.X-Frame-Options: DENY и Referrer-Policy: no-referrer.Артефакты записываются в PHISH_DATA_DIR (по умолчанию /data, Docker-том):
/data/
screenshots/ <collection-id>.png
html/ <collection-id>.html
assets/
<collection-id>/
<sha256-prefix>.js
<sha256-prefix>.css
Всё остальное (отпечатки, HTTP-логи, результаты паука, результаты плагинов, теги, заметки) хранится в PostgreSQL.
phishcollector/
collector/
browser.py # Захват Playwright, стелс-JS, ротация User-Agent
fingerprint.py # Все зонды отпечатков + PHISHING_PATTERNS + TECH_SIGNATURES
spider.py # Извлечение ссылок, robots.txt, sitemap, фаззинг по словарю
orchestrator.py # Жизненный цикл задачи: связывает все модули
plugins/
__init__.py # Датакласс CheckResult
urlhaus.py # Плагин abuse.ch URLhaus
virustotal.py # Плагин VirusTotal v3
runner.py # Запускает включённые плагины параллельно
api/
routes.py # Эндпоинты FastAPI
main.py # Точка входа приложения, CORS, auth middleware
models.py # ORM-модели SQLAlchemy
config.py # Настройки Pydantic (переменные окружения)
database.py # Движок, фабрика сессий, миграции схемы
frontend/
app.js # SPA на чистом JavaScript
style.css # Кибер-терминальный UI
nginx.conf # Обратный прокси + заголовки безопасности
wordlists/
phishing_paths.txt # Словарь паука по умолчанию
# Запустить только базу данных
docker compose up db -d
# Запустить API локально
pip install -r requirements.txt
playwright install chromium
uvicorn phishcollector.main:app --reload
# Запустить тесты (если есть)
pytest
| Переменная | Значение по умолчанию | Описание |
|---|
PHISH_DATABASE_URL | postgres://… | DSN PostgreSQL |
PHISH_API_KEY | (пусто) | Если установлен, все запросы требуют X-API-Key: <значение> |
PHISH_DATA_DIR | /data | Корневая папка для скриншотов, HTML, ресурсов |
PHISH_BROWSER_TIMEOUT | 30000 | Таймаут загрузки страницы в мс |
PHISH_REQUEST_TIMEOUT | 15 | Таймаут HTTP-подзапросов в секундах |
PHISH_MAX_SPIDER_PAGES | 50 | Максимальное количество URL, которые паук посещает за задачу |
PHISH_MAX_ASSET_SIZE | 10485760 | Максимальный размер JS/CSS файла для сохранения (байт) |
PHISH_PROXY_URL | (пусто) | Исходящий прокси — см. ниже |
PHISH_PROXY_SSL_VERIFY | true | Установите false для перехватывающих прокси — см. ниже |
PHISH_URLHAUS_ENABLED | false | Включить проверку репутации через URLhaus |
PHISH_VIRUSTOTAL_API_KEY | (пусто) | API-ключ VirusTotal v3 (оставьте пустым для отключения) |
| Метод | Путь | Описание |
|---|
POST | /collections | Отправить URL для сбора |
GET | /collections | Список всех коллекций |
GET | /collections/{id} | Полная информация + отпечаток |
GET | /collections/{id}/screenshot | Скриншот всей страницы в PNG |
GET | /collections/{id}/html | Сохранённый HTML (скачивается как простой текст) |
GET | /collections/{id}/requests | Журнал сетевых запросов |
GET | /collections/{id}/spider | Результаты паука |
GET | /collections/{id}/plugins | Результаты плагинов Threat Intel |
POST | /collections/{id}/plugins/refresh | Повторный запуск плагинов (например, для получения ожидающего результата VT) |
POST | /collections/{id}/rescan | Повторный сбор того же URL (оригинал сохраняется) |
PATCH | /collections/{id} | Обновить теги и заметки |
GET | /collections/{id}/export?format=json|csv | Экспорт данных коллекции |
DELETE | /collections/{id} | Удалить коллекцию и все её артефакты |
GET | /search | Поиск отпечатков по IP, хешу фавикона, технологии, стране, заголовку |