An invoice, a gift card, and 22 sets of credentials

The client handed us a list of email addresses and a one-line scope: test the people, not the servers. Within a week we ran two campaigns of very different calibers, one aimed at three people in finance, the other at the whole company, close to three thousand employees.
One user did everything the training says to do. He got an email, clicked, landed on a real login page, padlock and correct address and all. He typed his password, his phone buzzed, he approved the push. He saw his own inbox, his calendar, everything in place. The second factor worked exactly as designed.
In that same second his account stopped being his. Across both campaigns we walked away with 22 hijacked accounts, session tokens that shrugged off a password reset, and zero reports to the security team. Below is how we did it, mapped to MITRE ATT&CK.
Context
This one starts with why the client came to us: they wanted to test their people, not their servers, and they had two questions. Can an employee be talked into making a payment on an email alone? And does MFA really protect accounts, or does it just look like it does?
The answer to both was: it can be bypassed. One of those questions was settled by someone in accounting who wrote back that the payment to the swapped account would go out the same day.
Mail ran on Microsoft 365, some accounts had MFA turned on, and the security team expected that setup to be enough. It wasn't.
Challenge
On paper the mail setup looked reasonable. SPF closed the list of servers with a hard -all, DMARC ran in quarantine mode, and the built-in mail protection scanned attachments with an eagerness we later saw in the logs.
$ dig +short TXT klient.example "v=spf1 include:spf.protection.outlook.com -all" $ dig +short MX klient.example 0 klient-example.mail.protection.outlook.com. $ dig +short TXT _dmarc.klient.example "v=DMARC1; p=quarantine; rua=mailto:dmarc@klient.example; fo=1" $ dig +short TXT selector1._domainkey.klient.example # pusto -> DKIM po stronie nadawcy niepodpisany
One gap was visible right away. The domain didn't sign mail with DKIM, which in this mail environment is a matter of one toggle and a DNS record. On its own it doesn't open the door, but it weakens what DMARC rests on.
The real problem was elsewhere. MFA. Classic password phishing breaks on the second factor, because the thief has the login and password but a code or an app push still shows up at sign-in. To get through it for real, you steal the session, not the password. There was also the mail protection that reads everything on the user's behalf before they click a thing. That one we turned into a data source, more on that shortly.
What we did
We split the campaign into two stages with different risk profiles. Targeted spear phishing at three people in finance and broad phishing at the whole company. The MITRE ATT&CK mapping is below, since that's the easiest language to share with a blue team.
Stage 1: spear phishing at finance. Three addresses, three people who handle payments. We registered a domain that differed from the real vendor's by a single added word, stood up a sending account on it, and rebuilt the partner's invoice. Typography, layout, logos, file size, metadata. The email signature was copied down to the pixel. On the invoice, with the client's consent, we swapped the IBAN, so we could show the full payment-fraud path and not just a click.
To each message we attached a second PDF carrying a canary token. It's a digital trap that fires a signal the moment the document opens and reports who opened it, when, and from what address. This is where it gets interesting for anyone who has ever taken email open rates at face value.
open src=<chmura dostawcy poczty> org="Microsoft Corporation" geo=SE -> bot (skan załącznika) open src=<chmura dostawcy poczty> org="Microsoft Corporation" geo=PL -> bot open src=<krajowy operator> org="operator lokalny" geo=PL -> realny użytkownik
The pattern spoke for itself. On one token we counted ten automated opens and just one open by a real user. On another, no users at all, only scanners. The takeaway for an analyst is simple. If you build an alert on "file was opened," then in an environment like this the thing setting it off is mostly cloud infrastructure, not an attacker. Filtering by ASN and geolocation turns the noise into a signal.
The most important event had nothing to do with technology. One person forwarded the email, and back down the chain came a reply from the employee closing the process: we're paying today. No exploit. A believable invoice, the pressure of a payment deadline, and trust in a familiar brand were enough to set the transfer in motion.
Stage 2: mass phishing and the MFA bypass. The pretext was simple and catchy. A gift card from a well-known provider, supposedly granted through a company program. Nobody looks a gift horse in the mouth, so the scenario sold itself.
Instead of stealing passwords, we played the Adversary in the Middle. On a cloud-provider VPS we stood up a reverse proxy that captured the session, and we parked the domains on Cloudflare. The victim saw a real login form, because it was a real form, just passed through us.
The key is what happens behind the scenes. The user went through normal MFA, approved the app push, signed in, and saw their inbox. Meanwhile we pulled the session cookie out of the traffic. A session token is not a password. It works after a password change and slips past the second factor, because authentication already happened. We confirmed access to one of the accounts by hand, opening the mailbox without signing in again.
There was one more trick against detection. In front of the phishing site we put a firewall with a geo filter that let through only traffic from Poland. The anti-phishing bots that visit suspicious links from all over the world hit a wall and had nothing to report to a blocklist.
Two things caught our eye in this run. Opens and clicks moved almost in lockstep, which is a bot signature, because a scanner hits the link in one pass. And through the whole campaign nobody used the "report phishing" button. That told us more than the hijacked accounts did.
Result
We collected 22 sets of login credentials for the client's environment, and for most of them we also had session tokens, which means access that survives a password reset and the MFA as it stood. On the finance side, one email chain led to a stated intent to wire money to the swapped account. Google Safe Browsing flagged one of the domains only after a full day, and the client noticed the second one quarantined a day after launch, so the window to operate was wide either way.
User interaction was required, but past that the bar to entry was low, and taking over an identity let us move beyond the account we started from.
We wrote the recommendations so you can check them off, not just read them:
- Move to phishing-resistant MFA, meaning FIDO2 or passkeys. AiTM works because a code and a push can be relayed in real time, but a hardware key bound to the origin cannot.
- Tighten Conditional Access. Requiring a compliant device or a trusted location breaks the scenario where a token leaks to the attacker's machine. Microsoft's guidance on defending against AiTM is the reference point.
- Shorten session lifetime and turn on continuous access evaluation (CAE), so a stolen token doesn't live for weeks.
- Add DKIM signing on the sending side and read the DMARC RUA reports regularly. The
ruamailbox exists so that someone looks at it. - Introduce two-person payment approval and a hard check on any IBAN change through a channel other than email. That stops BEC even when the invoice looks perfect.
- Put a "report phishing" button where people actually look, and count how often it gets used. No reports despite plenty of clicks isn't the users' fault, it's the absence of an easy way to report.
One caveat to close, because we won't sell certainty we don't have. We don't know how many of those 22 accounts could have been turned into full lateral movement, because the scope ended at confirming access. We assume quite a few, given that the hijacked sessions included accounts with access to shared mailboxes.
So if someone at your company got an email today with an invoice for a small amount from a regular vendor, correct signature, a little deadline pressure, at what stage would you catch it? At the person, at Conditional Access, or at the payment procedure? If you can't answer all three with confidence, we're glad to test it.
Book a call with a consultant. We'll walk through the scope, the risks, and what a campaign like this could look like at your company.
All case studies are anonymized by sector, without names, dates or any data that could identify the client, in line with confidentiality. We never publish real vulnerabilities or client technical data.