
PhishCollector는 피싱 사이트를 수집, 분석 및 추적하기 위한 연구 프레임워크입니다.
PhishCollector는 피싱 사이트를 수집, 분석 및 추적하기 위한 연구 프레임워크입니다. 이 프레임워크는 의도적으로 시작점으로 설계되었습니다. 탐지 규칙, 기술 시그니처, 단어 목록 및 플러그인은 모두 일반 데이터 구조로 되어 있어, 연구자들이 읽고, 확장하고, 자신의 위협 환경에 맞게 조정할 수 있습니다.
의심스러운 URL을 제출하면 PhishCollector는 다음을 수행합니다:
모든 결과는 REST API, 웹 대시보드 및 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초마다 자동으로 다시 가져옵니다.
각 플러그인은 하나의 async 함수를 노출하는 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", "코드 내 무료 이메일 주소"),
],
"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, UA 로테이션
fingerprint.py # 모든 핑거프린팅 프로브 + PHISHING_PATTERNS + TECH_SIGNATURES
spider.py # 링크 추출, robots.txt, 사이트맵, 단어 목록 퍼징
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 | postgresql://… | 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, 파비콘 해시, 기술, 국가, 제목으로 핑거프린트 검색 |