
Kali365 - EvilTokens-Replik
Ein Device-Code-Phishing-Server für die Gegneremulation. Erfasst Microsoft 365 OAuth-Tokens über den Device Authorization Grant-Flow. Inspiriert von GraphSpy.
Warnung – Nur für autorisierte Nutzung. Dieses Tool ist für Penetrationstester und Red Teams bestimmt, die unter expliziter schriftlicher Autorisierung arbeiten. Missbrauch kann gegen Computerschutzgesetze verstoßen.
microsoft.com/devicelogin zu authentifizieren.Python-Backend (ein Port pro Kampagne) + nginx-Frontend + SQLite-Persistenz.
main_server.py ← einheitlicher Einstiegspunkt (diesen ausführen)
db.py ← SQLite-Persistenzschicht
html_enroll.py ← Erstellungsseite für die Opfer-Registrierung
html_search.py ← Erstellungsseite für die Opfer-Suche nach der Authentifizierung
css_shared.py ← gemeinsames CSS für die Operator-Benutzeroberfläche
nginx_helper.py ← generiert automatisch und lädt die nginx-Reverse-Proxy-Konfiguration neu
nginx.conf ← Basis-nginx-Konfiguration (enthält /etc/nginx/conf.d/*.conf)
| Methode | Pfad | Zielgruppe | Beschreibung |
|---|---|---|---|
GET | / | Opfer | Gerätecode-Registrierungsseite (Dunder-Mifflin-Design) |
POST | /poll | Opfer (JS) | Fragt den MS-Token-Endpunkt ab; speichert Token bei Erfolg |
GET | /search?s=<id> | Opfer | Suchseite nach der Authentifizierung (OneDrive/E-Mail) |
GET | /app | Operator | Dashboard – Statistiken + letzte Erfassungen |
GET | /app/device-codes | Operator | Alle Kampagnen mit Live-Poll-Status |
POST | /app/device-codes/new | Operator | Neue Gerätecode-Kampagne erstellen |
GET | /app/tokens | Operator | Alle erfassten Tokens |
GET | /app/search?id=<id> | Operator | OneDrive + E-Mail-Suche für ein bestimmtes Token |
POST | /webhook | Relay-Knoten | Token von einem authentifizierten Relay-Knoten übernehmen |
POST | /relay/checkin | Relay-Knoten | Relay-Knoten registrieren; gibt node_id zurück |
Wenn eine Kampagne mit einer Domain erstellt wird, schreibt nginx_helper.py automatisch einen Pro-Domain-Server-Block in NGINX_CONF (standardmäßig /etc/nginx/conf.d/easytokens.conf) und lädt nginx neu. Der Opferverkehr, der auf Port 80 für diese Domain eintrifft, wird an die richtige Python-Serverinstanz weitergeleitet.
nginx.conf verwirft jede Anfrage, deren Host-Header keiner bekannten Kampagne entspricht (return 444), um eine versehentliche Offenlegung des Python-Backends zu verhindern.NGINX_CONF='' oder NGINX_RELOAD_CMD='', um die automatische nginx-Verwaltung zu deaktivieren.docker compose up --build
Von Docker bereitgestellte Ports:
| Port | Zweck |
|---|---|
80 | nginx — domainbasierter Opferverkehr |
3000 | Python — Operator-Benutzeroberfläche + direkter Opferzugriff |
http://localhost:3000/http://localhost:3000/apphttp://<kampagnen-domain>/ (über nginx auf Port 80 geleitet)Erfasste Tokens und Logs werden in Docker-Volumes persistiert:
| Volume | Pfad im Container | Zweck |
|---|---|---|
easytokens-data | /data/easytokens.db | SQLite-Datenbank |
./logs | /logs/ | Pro-Anfrage-Logdateien |
Voraussetzungen: Python 3.12+, keine Drittanbieterpakete.
python main_server.py
| Variable | Standard | Beschreibung |
|---|---|---|
PORT | 3000 | Listening-Port für den Python-Server |
PORT_MAX | 3010 | Obergrenze des von Docker bereitgestellten Portbereichs |
DB_PATH | /data/easytokens.db | Pfad zur SQLite-Datenbank |
LOG_DIR | /logs | Verzeichnis für Pro-Anfrage-Logs |
NGINX_CONF | /etc/nginx/conf.d/easytokens.conf | Pfad, in den nginx_helper die generierte Konfiguration schreibt; auf '' setzen, um zu deaktivieren |
NGINX_RELOAD_CMD | nginx -s reload | Shell-Befehl zum Neuladen von nginx nach Konfigurationsänderungen; auf '' setzen, um zu deaktivieren |
RELAY_SECRET | (nicht gesetzt) | Gemeinsames Geheimnis für die Authentifizierung des Relay-Knotens. Mit openssl rand -hex 32 generieren. Muss mit RELAY_SECRET in php-relay/.env übereinstimmen. Nicht gesetzt lassen, um Relay-Unterstützung zu deaktivieren. |
Das Verzeichnis php-relay/ enthält einen eigenständigen Apache/PHP-Container, der als verteilter Opfer-Knoten fungiert. Er stellt dieselbe Gerätecode-Registrierungsseite wie der Hauptserver bereit, fragt Microsoft direkt ab und leitet erfasste Tokens über POST /webhook an das Hauptpanel weiter.
checkin.php einen POST an POST /relay/checkin auf dem Hauptpanel und authentifiziert sich mit RELAY_SECRET. Das Panel registriert den Knoten und gibt eine node_id zurück.index.php) auf, die einen neuen Gerätecode-Flow startet.poll.php ab. Wenn ein Token erfasst wird, leitet poll.php es an POST /webhook auf dem Hauptpanel weiter, versehen mit der node_id.Konfigurieren in php-relay/.env:
| Variable | Standard | Beschreibung |
|---|---|---|
MAIN_SERVER_URL | http://easytokens:3000 | URL des Hauptpanels, die vom Relay-Container aus erreichbar ist |
RELAY_SECRET | (erforderlich) | Muss mit RELAY_SECRET auf dem Hauptpanel übereinstimmen |
RELAY_PORT | 8082 | Host-Port, um das Relay bereitzustellen |
RELAY_LABEL | Hostname | Menschenlesbarer Name, der im Panel für diesen Knoten angezeigt wird |
CHECKIN_RETRIES | 10 | Anzahl der Wiederholungsversuche für das Check-in, bevor aufgegeben wird |
CHECKIN_DELAY | 5 | Sekunden zwischen Check-in-Wiederholungen |
NODE_ID_FILE | /tmp/relay_node_id | Pfad, in dem die node_id nach dem Check-in zwischengespeichert wird |
Beide Container gleichzeitig (empfohlen):
# von EasyTokens/
docker compose -f docker-compose.yml -f php-relay/docker-compose.yml up --build
Die gemeinsame Ausführung mit einem einzigen -f-Merge platziert sie im selben Docker-Netzwerk, sodass MAIN_SERVER_URL=http://easytokens:3000 korrekt aufgelöst wird.
Zugriff:
| URL | Zweck |
|---|---|
http://localhost:8082/ | Relay-Opfer-Registrierungsseite |
http://localhost:3000/app/nodes | Operator-Ansicht der registrierten Relay-Knoten |
Nur Relay (entferntes Panel):
cd php-relay
# Setzen Sie MAIN_SERVER_URL in .env auf die öffentliche Panel-URL
docker compose up --build