
Kali365 - EvilTokens Replica
적대자 모의 훈련을 위한 디바이스 코드 피싱 서버입니다. 디바이스 권한 부여 흐름을 통해 Microsoft 365 OAuth 토큰을 캡처합니다. GraphSpy에서 영감을 받았습니다.
경고 — 승인된 사용만 가능합니다. 이 도구는 명시적인 서면 승인을 받은 침투 테스터 및 레드 팀 운영자를 대상으로 합니다. 오용 시 컴퓨터 사기 관련 법률을 위반할 수 있습니다.
microsoft.com/devicelogin에서 인증하도록 안내합니다.Python 백엔드(캠페인당 하나의 포트) + nginx 프론트엔드 + SQLite 영구 저장소.
main_server.py ← 통합 진입점 (이 파일을 실행)
db.py ← SQLite 영구 저장소 계층
html_enroll.py ← 피해자 등록 페이지 빌더
html_search.py ← 피해자 인증 후 검색 페이지 빌더
css_shared.py ← 운영자 UI용 공유 CSS
nginx_helper.py ← nginx 리버스 프록시 설정 자동 생성 및 리로드
nginx.conf ← 기본 nginx 설정 (/etc/nginx/conf.d/*.conf 포함)
도메인이 설정된 캠페인이 생성되면 nginx_helper.py는 자동으로 도메인별 서버 블록을 NGINX_CONF(기본값 /etc/nginx/conf.d/easytokens.conf)에 작성하고 nginx를 리로드합니다. 해당 도메인으로 포트 80에 도착하는 피해자 트래픽은 올바른 Python 서버 인스턴스로 프록시됩니다.
nginx.conf는 알려진 캠페인과 일치하지 않는 Host 헤더가 있는 모든 요청을 드롭(return 444)하여 Python 백엔드의 우발적 노출을 방지합니다.NGINX_CONF='' 또는 NGINX_RELOAD_CMD=''를 설정하세요.docker compose up --build
Docker가 노출하는 포트:
| 포트 | 용도 |
|---|---|
80 | nginx — 도메인 기반 피해자 트래픽 |
3000 | Python — 운영자 UI + 직접 피해자 접근 |
http://localhost:3000/http://localhost:3000/apphttp://<campaign-domain>/ (nginx를 통해 포트 80으로 라우팅)캡처된 토큰과 로그는 Docker 볼륨에 유지됩니다:
| 볼륨 | 컨테이너 내 경로 | 용도 |
|---|---|---|
easytokens-data | /data/easytokens.db | SQLite 데이터베이스 |
./logs | /logs/ | 요청별 로그 파일 |
요구 사항: Python 3.12+, 서드파티 패키지 불필요.
python main_server.py
php-relay/ 디렉터리에는 독립형 Apache/PHP 컨테이너가 포함되어 있으며, 이 컨테이너는 분산된 피해자 대면 노드 역할을 합니다. 메인 서버와 동일한 디바이스 코드 등록 페이지를 제공하고, Microsoft에 직접 폴링하며, 캡처된 토큰을 POST /webhook을 통해 메인 패널로 전달합니다.
checkin.php는 메인 패널의 POST /relay/checkin에 POST 요청을 보내고 RELAY_SECRET으로 인증합니다. 패널은 노드를 등록하고 node_id를 반환합니다.index.php)를 방문하여 새로운 디바이스 코드 흐름을 시작합니다.poll.php를 폴링합니다. 토큰이 캡처되면 poll.php는 해당 토큰을 node_id와 함께 메인 패널의 POST /webhook으로 전달합니다.php-relay/.env에서 구성:
두 컨테이너 동시 실행 (권장):
# EasyTokens/ 디렉터리에서
docker compose -f docker-compose.yml -f php-relay/docker-compose.yml up --build
단일 -f 병합으로 두 컨테이너를 동일한 Docker 네트워크에 배치하면 MAIN_SERVER_URL=http://easytokens:3000이 올바르게 확인됩니다.
접근:
| URL | 용도 |
|---|---|
http://localhost:8082/ | 릴레이 피해자 등록 페이지 |
http://localhost:3000/app/nodes | 등록된 릴레이 노드의 운영자 보기 |
릴레이만 실행 (원격 패널):
cd php-relay
# .env에서 MAIN_SERVER_URL을 공개 패널 URL로 설정
docker compose up --build
openssl rand -hex 32EasyTokens/.env에 RELAY_SECRET=<secret> 설정 (docker-compose.yml을 통해 메인 패널에서 참조)php-relay/.env에 동일한 값 설정SQLite 데이터베이스의 두 테이블:
tokens — 캡처된 모든 액세스/리프레시 토큰 (UPN, 액세스 토큰, 리프레시 토큰, ID 토큰, 범위, 출처, 캡처 타임스탬프)device_codes — 운영자가 시작한 캠페인 (사용자 코드, 디바이스 코드, 확인 URL, 상태, 연결된 토큰 ID, 포트, 도메인)MIT — 저작권 (c) 2026 Casey Smith
| 메서드 | 경로 | 대상 | 설명 |
|---|
GET | / | 피해자 | 디바이스 코드 등록 페이지 (Dunder Mifflin 테마) |
POST | /poll | 피해자 (JS) | MS 토큰 엔드포인트 폴링; 성공 시 토큰 저장 |
GET | /search?s=<id> | 피해자 | 인증 후 OneDrive/이메일 검색 페이지 |
GET | /app | 운영자 | 대시보드 — 통계 + 최근 캡처 목록 |
GET | /app/device-codes | 운영자 | 모든 캠페인 및 실시간 폴 상태 |
POST | /app/device-codes/new | 운영자 | 새 디바이스 코드 캠페인 생성 |
GET | /app/tokens | 운영자 | 모든 캡처된 토큰 |
GET | /app/search?id=<id> | 운영자 | 특정 토큰에 대한 OneDrive + 이메일 검색 |
POST | /webhook | 릴레이 노드 | 인증된 릴레이 노드로부터 토큰 수집 |
POST | /relay/checkin | 릴레이 노드 | 릴레이 노드 등록; node_id 반환 |
| 변수 | 기본값 | 설명 |
|---|
PORT | 3000 | Python 서버 수신 포트 |
PORT_MAX | 3010 | Docker가 노출하는 포트 범위의 상한 |
DB_PATH | /data/easytokens.db | SQLite 데이터베이스 경로 |
LOG_DIR | /logs | 요청별 로그 디렉터리 |
NGINX_CONF | /etc/nginx/conf.d/easytokens.conf | nginx_helper가 생성한 설정을 작성할 경로; ''로 설정하면 비활성화 |
NGINX_RELOAD_CMD | nginx -s reload | 설정 변경 후 nginx를 리로드하는 셸 명령; ''로 설정하면 비활성화 |
RELAY_SECRET | (설정되지 않음) | 릴레이 노드 인증용 공유 비밀. openssl rand -hex 32로 생성. php-relay/.env의 RELAY_SECRET과 일치해야 함. 설정하지 않으면 릴레이 지원 비활성화. |
| 변수 | 기본값 | 설명 |
|---|
MAIN_SERVER_URL | http://easytokens:3000 | 릴레이 컨테이너 내부에서 접근 가능한 메인 패널 URL |
RELAY_SECRET | (필수) | 메인 패널의 RELAY_SECRET과 일치해야 함 |
RELAY_PORT | 8082 | 릴레이를 노출할 호스트 포트 |
RELAY_LABEL | 호스트명 | 패널에 표시될 이 노드의 사람이 읽을 수 있는 이름 |
CHECKIN_RETRIES | 10 | 포기 전 체크인 재시도 횟수 |
CHECKIN_DELAY | 5 | 체크인 재시도 간격(초) |
NODE_ID_FILE | /tmp/relay_node_id | 체크인 후 node_id가 캐시되는 경로 |
| 필드 | 값 |
|---|
| 클라이언트 ID | d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office) |
| 리소스 | https://graph.microsoft.com |
| 범위 | openid profile email offline_access Mail.Read Files.Read |
| 디바이스 코드 URL | https://login.microsoftonline.com/common/oauth2/devicecode |
| 토큰 URL | https://login.microsoftonline.com/Common/oauth2/token |