Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
EasyTokens — Kali365 - EvilTokens Replica | Kitploit
Tools/GitHubGitHub/secdev02/easytokens
OSINT for Social EngineeringInformation GatheringPost-ExploitationPhishingPenetration TestingCloud SecurityCommand and ControlAuthenticationRed TeamingAdversarial Attack
GitHubsecdev02/easytokens

EasyTokens

72121 month agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Kali365 - EvilTokens Replica

View Repository

EasyTokens

A device-code phishing server for adversary emulation. Captures Microsoft 365 OAuth tokens via the Device Authorization Grant flow. Inspired by GraphSpy.

Warning — Authorized Use Only. This tool is intended for penetration testers and red teamers operating under explicit written authorization. Misuse may violate computer fraud laws.


How It Works

  1. Operator creates a device code campaign via the operator UI.
  2. A victim-facing enrollment page (Dunder Mifflin themed) displays the user code and prompts the target to authenticate at microsoft.com/devicelogin.
  3. A background poller detects when the target completes authentication and stores the captured access/refresh token in SQLite.
  4. The victim's browser is redirected to a post-auth search page.
  5. The operator can search the victim's OneDrive and email via Microsoft Graph using the captured token.

Architecture

Python backend (one port per campaign) + nginx front-end + SQLite persistence.

root@kitploit:~
main_server.py          ← unified entry point (run this)
db.py                   ← SQLite persistence layer
html_enroll.py          ← victim enrollment page builder
html_search.py          ← victim post-auth search page builder
css_shared.py           ← shared CSS for operator UI
nginx_helper.py         ← auto-generates and reloads nginx reverse-proxy config
nginx.conf              ← base nginx config (includes /etc/nginx/conf.d/*.conf)

Routes


Nginx — Domain Campaigns

When a campaign is created with a domain set, nginx_helper.py automatically writes a per-domain server block to NGINX_CONF (/etc/nginx/conf.d/easytokens.conf by default) and reloads nginx. Victim traffic arriving on port 80 for that domain is proxied to the correct Python server instance.

  • Campaigns without a domain are served directly on the Python port (default 3000).
  • Campaigns with a domain are served through nginx on port 80.
  • The base nginx.conf drops any request whose Host header does not match a known campaign (return 444), preventing accidental exposure of the Python backend.
  • Set NGINX_CONF='' or NGINX_RELOAD_CMD='' to disable automatic nginx management.

Quick Start (Docker)

root@kitploit:~
docker compose up --build

Ports exposed by Docker:

PortPurpose
80nginx — domain-based victim traffic
3000Python — operator UI + direct victim access
  • Victim page (direct): http://localhost:3000/
  • Operator UI: http://localhost:3000/app
  • Domain campaigns: http://<campaign-domain>/ (routed through nginx on port 80)

Captured tokens and logs are persisted to Docker volumes:

VolumePath in containerPurpose
easytokens-data/data/easytokens.dbSQLite database
./logs/logs/Per-request log files

Manual Setup

Requirements: Python 3.12+, no third-party packages.

root@kitploit:~
python main_server.py

Environment Variables


PHP Relay Node

The php-relay/ directory contains a standalone Apache/PHP container that acts as a distributed victim-facing node. It serves the same device-code enrollment page as the main server, polls Microsoft directly, and forwards captured tokens to the main panel via POST /webhook.

How It Works

  1. On startup, checkin.php POSTs to POST /relay/checkin on the main panel, authenticating with RELAY_SECRET. The panel registers the node and returns a node_id.
  2. Victims browse to the relay's enrollment page (index.php), which initiates a fresh device-code flow.
  3. Browser-side JS polls poll.php. When a token is captured, poll.php forwards it to POST /webhook on the main panel, tagged with the node_id.

Relay Environment Variables

Configure in php-relay/.env:

Quick Start

Both containers simultaneously (recommended):

root@kitploit:~
# from EasyTokens/
docker compose -f docker-compose.yml -f php-relay/docker-compose.yml up --build

Running both with a single -f merge puts them on the same Docker network, so MAIN_SERVER_URL=http://easytokens:3000 resolves correctly.

Access:

URLPurpose
http://localhost:8082/Relay victim enrollment page
http://localhost:3000/app/nodesOperator view of registered relay nodes

Relay only (remote panel):

root@kitploit:~
cd php-relay
# Set MAIN_SERVER_URL to the public panel URL in .env
docker compose up --build

Shared Secret Setup

  1. Generate a secret: openssl rand -hex 32
  2. Set RELAY_SECRET=<secret> in EasyTokens/.env (picked up by the main panel via docker-compose.yml)
  3. Set the same value in php-relay/.env

Database

Two tables in the SQLite database:

  • tokens — every captured access/refresh token (UPN, access token, refresh token, id token, scope, source, capture timestamp)
  • device_codes — operator-initiated campaigns (user code, device code, verification URL, status, linked token ID, port, domain)

Microsoft OAuth Details


License

MIT — Copyright (c) 2026 Casey Smith

Download Tool
MethodPathAudienceDescription
GET/VictimDevice-code enrollment page (Dunder Mifflin theme)
POST/pollVictim (JS)Polls MS token endpoint; stores token on success
GET/search?s=<id>VictimPost-auth OneDrive/email search page
GET/appOperatorDashboard — stats + recent captures
GET/app/device-codesOperatorAll campaigns with live poll status
POST/app/device-codes/newOperatorCreate a new device code campaign
GET/app/tokensOperatorAll captured tokens
GET/app/search?id=<id>OperatorOneDrive + email search for a specific token
POST/webhookRelay nodeIngest a token from an authenticated relay node
POST/relay/checkinRelay nodeRegister a relay node; returns node_id
VariableDefaultDescription
PORT3000Listening port for the Python server
PORT_MAX3010Upper bound of port range exposed by Docker
DB_PATH/data/easytokens.dbSQLite database path
LOG_DIR/logsPer-request log directory
NGINX_CONF/etc/nginx/conf.d/easytokens.confPath nginx_helper writes generated config to; set to '' to disable
NGINX_RELOAD_CMDnginx -s reloadShell command to reload nginx after config changes; set to '' to disable
RELAY_SECRET(unset)Shared secret for relay node authentication. Generate with openssl rand -hex 32. Must match RELAY_SECRET in php-relay/.env. Leave unset to disable relay support.
VariableDefaultDescription
MAIN_SERVER_URLhttp://easytokens:3000URL of the main panel reachable from inside the relay container
RELAY_SECRET(required)Must match RELAY_SECRET on the main panel
RELAY_PORT8082Host port to expose the relay on
RELAY_LABELhostnameHuman-readable name shown in the panel for this node
CHECKIN_RETRIES10Check-in retry attempts before giving up
CHECKIN_DELAY5Seconds between check-in retries
NODE_ID_FILE/tmp/relay_node_idPath where the node_id is cached after check-in
FieldValue
Client IDd3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)
Resourcehttps://graph.microsoft.com
Scopesopenid profile email offline_access Mail.Read Files.Read
Device code URLhttps://login.microsoftonline.com/common/oauth2/devicecode
Token URLhttps://login.microsoftonline.com/Common/oauth2/token