GhostLoot part 2: the Microsoft cookie mess, the inbox, and the Google wall
Part 1 got the loot out of Evilginx's session list. Part 2 is what I learned the hard way after that: which Microsoft cookie is actually money, which "TTL" is a fiction, how the panel had to stop being a spreadsheet, and why a stock Google phishlet will waste your week.
Evilginx 3.3.0 Community. GhostLoot 1.6.1. Still authorized work only. Still a read-only viewer.
The Tuesday that looked like a broken tool
Smoke-test. Personal Microsoft account into an o365-shaped phishlet. Capture comes back. I open the cookies. MSPAuth: Disabled. Or worse, a stub that looks like a session until you stare at it.
First thought: GhostLoot is wrong. It wasn't. Microsoft never issued a reusable session on the path I was on.
"Microsoft login" is two IdPs sharing a brand.
Entra is not MSA
Entra ID is work and school. Host: login.microsoftonline.com. The cookies that matter are ESTSAUTH (non-persistent: about 24 hours or until the browser closes) and ESTSAUTHPERSISTENT (persistent SSO: up to 90 days of inactivity, rolling, until revoked). Replay means import on https://login.microsoftonline.com, then open https://www.office.com. Outlook on the web is Entra territory. A personal MSAAUTHP will not SSO you into it.
MSA is personal Microsoft accounts — including a Gmail you registered as a Microsoft account, including passwordless Authenticator-only. Host: login.live.com. For passwordless, the cookie that matters is __Host-MSAAUTHP. It persists across browser close. Microsoft does not publish a Max-Age. Anyone quoting "one year" is guessing. __Host-MSAAUTH=11 is a deleted stub, not loot. Password MSA can show __Host-MSAAUTH with a real long value; that one is not persistent.
Replay for MSA: import on https://login.live.com, then https://account.microsoft.com. Avoid https://outlook.live.com — you do not get SSO from MSAAUTHP there.
Throw a personal account at an Entra-wired phishlet and Microsoft quietly routes you into the consumer stack. Different hosts. Different cookies. The proxy collects flow junk. The session never closes cleanly. You get Disabled. That is a coverage problem, not "AiTM fails on personal accounts."
I ended up with one microsoft.yaml covering both stacks, redirect-on-capture after loot. Separate o365-only files for personal accounts were the wrong shape.
The stock Evilginx completion lie
Community Evilginx has a footgun: AllCookieAuthTokensCaptured wants all listed tokens.
A live MSA capture will never carry ESTSAUTH. A live Entra capture will never carry MSAAUTHP. So the session never "completes," even when you are holding the one cookie that actually replays.
The patch that made ops sane: treat the session as captured when any required non-junk token is present.
Junk that must never count as loot: empty, Disabled, estsfd, 11, length ≤ 2.
The name-fold bug that refused to match
Go lowercases cookie names. strings.ToLower("__Host-MSAAUTHP") becomes __host-msaauthp — two a's in msaa.
I wrote a switch case as __host-msauthp — one a. It never matched. The panel kept calling good MSA loot invalid while I stared at a cookie that was sitting right there.
Tests that earned their keep: PasswordlessMSA, PasswordMSA, TestMSCookieNameFold. If you fold names, count the a's.
The TTL lie
Evilginx's CookieToken does not store Set-Cookie Expires. So any countdown you invent in a UI is fan fiction.
GhostLoot's panel only shows kinds it can defend: parsed (JWT exp when the cookie actually is a JWT), idle90d, idle24h, session, persistent, unknown. No now+1y. No fake 89-day ticker.
TTL lives in the inspector as context. The scan signal is freshness: captures under fifteen minutes get a copper highlight; default sort is recency. When you are juggling Telegram alerts, "is this still warm" beats "is this theoretically ninety days."
Turning the panel into an inbox
After part 1 I kept bolting columns. Then I ripped them out. Then I put some back. The only job that mattered: Telegram ping → about twenty seconds → replay or bounce → notes. Manual. No auto-replay. GhostLoot still never writes phishlets and never talks to live Evilginx — copy ~/.evilginx/data.db (buntdb), parse, delete the copy. Default listen 127.0.0.1:8090. One Go binary, index.html embedded with go:embed. Version in production: 1.6.1.
The panel is an inbox now.
Tabs: Inbox, Captures, Lures, Settings. Dashboard collapsed into a period strip on Lures — not a place you live. Keyboard: 1–4, j/k, c copy cookies, b brief, h Cookie header, u done, e bounced, ?.
Inbox columns that survived: account + status tag, loot type (Entra ID / Microsoft account), password blurred, from (CC · city · UA), expires (honest label), when (relative + absolute). Geo is optional via ip-api.com with a local JSON cache; -nogeo turns it off. Still never send lure URLs to Safe Browsing, VirusTotal, or urlscan.
Statuses are three: open, bounced, done. I tried copied / replayed. They confused me mid-op, so they folded back into open. Bounce reasons persist: CA / IP mismatch / UA / token dead.
Replay inspector is a checklist, not a pretty card:
- VPN/exit — country · city · AS… and Copy UA
- Import on
login.microsoftonline.comorlogin.live.com - Then open
office.com/account.microsoft.com
One primary Copy cookies. Accept-Language (suggested from country, not captured), Cookie header, long briefing — behind More.
Telegram on the wire is Spanish and thin: #46 · hace 40s, type, persist, user (unless minimal mode), country, UA, import/then/avoid. Never the cookie. Never the password. Minimal mode drops account and IP when that alert leaves your perimeter.
One command from the laptop
ghostloot on the laptop: if localhost:8090 is down, it builds ssh -L 8090:127.0.0.1:8090 with ControlMaster. It does not pkill ssh. ghostloot down stops the panel systemd unit and closes that tunnel. ghostloot console attaches the Evilginx tmux — and yes, root and ubuntu use different sockets (/tmp/tmux-0 vs /tmp/tmux-1000); the CLI finds the session owner instead of guessing.
Server side: systemd unit ghostloot on 127.0.0.1:8090, config /etc/ghostloot.conf. Laptop config under ~/.ghostloot/. sudo ./install.sh hunts data.db, the Evilginx binary, and a free loopback port in 8090–8094.
Bugs that only show up when you actually run it:
- Template called
.sizeon an Array (ips.size→ undefined IPs). - API said
update/landing; UI expectedupdate_time/landing_url. go.modwanted 1.24; VPS had 1.22 — lowered the module.- Copying the binary onto itself while it was running →
ETXTBSY. Kill whatever is on 8090 first. Do notpkillthe SSH tunnel that is keeping you in.
The Google wall
I will say this once, without a tutorial.
Public google.yaml files (the usual Community collections, min_ver: 2.3.0 and friends) will load. Login becomes WebLiteSignIn / /v3/signin/identifier. Next is a JS button (identifierNext). bgresponse defaults toward js_disabled. Botguard / reCAPTCHA Enterprise sits on the path. Force a POST with the email and you still land on /v3/signin/rejected?...&rhlk=js.
Hostname rewrite, extra proxy_hosts, Cloudflare Origin in front of the lure — none of that mints Botguard. Community cannot do Google properly. Pro uses Evilpuppet. YAML will not save you. I am not publishing a bypass.
Cloudflare in front of a lure hides origin in DNS. New hostnames need origin certs. Let's Encrypt HTTP-01 against orange-cloud returns 403. Missing origin cert and the visitor gets 525. That is ops, not a Google breakthrough.
What actually stops AiTM
Password plus SMS, OTP, push, or emailed code does not. You capture after the second factor is done.
Phishing-resistant MFA does: FIDO2, passkeys, Windows Hello for Business, bound to the real origin. The browser will not hand that credential to your look-alike domain. Nothing to steal. If a tenant enforces that, the run dies at the door — write it up as a strength.
If the tenant has no 2FA at all, that is the tenant. It is not your phishlet "skipping" MFA.
OPSEC, still boring on purpose
Bind loopback, tunnel in. Off-localhost without -user/-pass refuses to start. CSRF origin check on POSTs. State files 0600. Do not park a second web app (GoPhish and friends) on 0.0.0.0:8080 on the same box. Mail from a warmed mailbox, not the proxy IP. Replay from a VPN in the victim's country with a cloned UA — not from the VPS. Optional geo is fine; shipping lure URLs to Google Safe Browsing is how infra dies.
Grab it
GhostLoot is MIT: github.com/marcocarolasec/ghostloot
Read-only viewer for a data.db you already have, on an engagement you are cleared to run. No Evilginx in the repo. No phishlets. No auto-replay.
If you have run Community Evilginx against Microsoft in 2026: did the Entra vs MSA split burn you too, or has a CE Google Next flow ever actually completed for you?





