
PhishCollectorは、フィッシングサイトの収集、分析、追跡のための研究フレームワークです。
PhishCollectorは、フィッシングサイトの収集、分析、追跡を行うための研究フレームワークです。意図的に出発点として設計されており、検出ルール、テクノロジーシグネチャ、ワードリスト、プラグインはすべてプレーンなデータ構造であり、研究者が自身の脅威環境に合わせて読み、拡張し、適応することが期待されています。
疑わしいURLを送信すると、PhishCollectorは以下を実行します。
すべての結果は、REST API、Webダッシュボード、CLIからアクセスできます。


cp .env.example .env # 設定(以下参照)
docker compose up --build # db + app + frontend を起動
| サービス | URL |
|---|---|
| GUI | http://localhost:3000 |
| APIドキュメント | http://localhost:8000/docs |
| DB | 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マン・イン・ザ・ミドルとして動作し、HTTPS接続ごとに独自のCA証明書を提示します。SSL検証を無効にしないと、プロキシ経由のすべてのHTTPSリクエストが失敗します。
PHISH_PROXY_URL=http://127.0.0.1:8080
PHISH_PROXY_SSL_VERIFY=false # Burp / インターセプトプロキシでは必須
注:
PHISH_PROXY_SSL_VERIFY=falseは、Pythonバックエンド(プラグイン、フィンガープリンター、スパイダー)が行うアウトバウンドHTTPS接続にのみ影響します。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}'
# インストール(コンテナ内またはrequirements.txtのあるローカルvenv)
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.abuse.ch からの無料Auth-Keyが必要です。
PHISH_URLHAUS_ENABLED=true
PHISH_URLHAUS_API_KEY=<your-auth-key>
virustotal.com からの無料または有料のAPIキーが必要です。
PHISH_VIRUSTOTAL_API_KEY=<your-key>
URLがまだVTで分析されていない場合、PhishCollectorはスキャン用に送信し、結果が得られるまで30秒ごとに自動的に再取得します。
各プラグインは phishcollector/plugins/ 内の単一ファイルで、1つの非同期関数を公開します。
# 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))
他の変更は不要です。結果は自動的に保存され、ダッシュボードに表示され、脅威スコアに反映されます。
検出エンジンは意図的にプレーンで読みやすいデータとして維持されており、研究者が追跡しているキットやキャンペーンに合わせて調整できます。すべては1つのファイルにあります。
phishcollector/collector/fingerprint.py
PHISHING_PATTERNS — レンダリングされたHTML + JSに対してスキャンされる正規表現ルール各エントリは (正規表現, 人間が読めるラベル) のタプルで、カテゴリごとにグループ化されています。いずれかのカテゴリで一致すると、インジケーター(Indicators) タブに表示され、脅威スコアに加算されます。
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", "コード内のフリーメールアドレス"),
],
"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", "小包配送のルアー"),
],
}
ルールを追加するには: 該当するカテゴリリストにタプルを追加します。 カテゴリを追加するには: 新しいキーを追加します — カテゴリ名が自動的にIndicatorsタブのセクションヘッダーとして表示されます。
# 例: 新たに発見されたキットのフィンガープリントを追跡
"my_campaign_2024": [
(r"panel\.php\?cmd=send", "既知のC2パネルパス"),
(r"X-Mailer:\s*PHPMailer\s*5\.2\.1", "キットで使用されている特定のPHPMailerバージョン"),
],
TECH_SIGNATURES — テクノロジー検出HTML、レスポンスヘッダー、Cookie、最終URLに対して照合されるシグネチャ。検出されたテクノロジーはテクノロジー(Technologies) パネルに表示され、すべての収集間で検索可能です。
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 にあります。1行に1パス、# はコメントです。一般的なフィッシングキットのパス(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、UAローテーション
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、認証ミドルウェア
models.py # SQLAlchemy ORMモデル
config.py # Pydantic設定(環境変数)
database.py # エンジン、セッションファクトリ、スキーママイグレーション
frontend/
app.js # Vanilla JS SPA
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://… | PostgreSQL DSN |
PHISH_API_KEY | (空) | 設定されている場合、すべてのリクエストに X-API-Key: <値> が必要 |
PHISH_DATA_DIR | /data | スクリーンショット、HTML、アセットのストレージルート |
PHISH_BROWSER_TIMEOUT | 30000 | ページ読み込みタイムアウト(ms) |
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 | (空) | VirusTotal v3 APIキー(空のままにすると無効) |
| メソッド | パス | 説明 |
|---|
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 | 脅威インテリジェンスプラグイン結果 |
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、ファビコンハッシュ、テクノロジー、国、タイトルでフィンガープリントを検索 |