Phishing-Resistant MFA: Why Everything Short of FIDO2 Is Living on Borrowed Time
Multi-factor authentication was supposed to make phishing obsolete. For a stretch of the 2010s it nearly did, because the attackers of that era were running bulk credential-stuffing campaigns against reused passwords, and a second factor — any second factor — broke that economy cold. Then the attackers adapted, and they adapted faster than the controls. A modern phishing kit does not ask you for a password and stop; it sits in the middle of your real login in real time, relays your one-time code to the actual site within its thirty-second window, and walks away with your authenticated session cookie. Another kind of attacker simply spams your phone with approval prompts until, tired and confused, you tap “yes.” A third buys your phone number from a bribed carrier rep and reads your SMS codes directly. By 2022 these were not theoretical; they were the documented root cause of breaches at Twilio, Uber, and dozens of other well-resourced companies in a single campaign season. The uncomfortable conclusion that fell out of that year is that most of what we call MFA is a speed bump, not a wall. The only factor that reliably survived contact with a competent attacker was the one cryptographically bound to the website’s identity — FIDO2 and WebAuthn — and the case for treating everything else as a stopgap is now overwhelming.
What MFA Was Supposed to Fix, and What It Actually Fixed
The original threat MFA addressed was credential reuse at scale. Users pick weak passwords, reuse them everywhere, and those passwords leak in breaches by the billion. An attacker with a dump can stuff those credentials against a thousand other sites and walk into every account where the user reused the password. A second factor defeats this completely: knowing the password is no longer sufficient, and the attacker running an automated stuffing campaign has no way to produce a live second factor for millions of accounts.
That is a real and enormous win, and it is why MFA should be on everywhere. But notice the precise shape of what it fixed. It defeated the attacker who has your password but is not present at your login. It did nothing about the attacker who is present — who can induce you to produce a second factor and capture it while it is still valid. And that is exactly the attacker who showed up next. The structural weakness is that most second factors are bearer tokens: a six-digit TOTP code, an SMS code, a push approval. Whoever holds the token within its validity window is authenticated. The protocol has no notion of who is asking for it. If the attacker can get the user to read out the code or tap the prompt, the attacker holds the bearer token, and the second factor has protected nothing.
The Attack Taxonomy: How Each Factor Falls
There are three distinct techniques in wide use, and they fall the factors in different ways.
Real-time phishing, or adversary-in-the-middle (AiTM). This is the decisive one. The attacker stands up a reverse proxy — Evilginx, EvilProxy, and Modlishka are the well-known toolkits — at a look-alike domain. The victim lands there, and the proxy transparently relays every byte to and from the genuine site. The victim sees the real login page (because it is the real page, proxied), enters their password, and is prompted for their second factor exactly as normal. They enter their TOTP code or approve the push. The proxy relays all of it to the real site in real time, the login succeeds, and the proxy captures the resulting session cookie. From that point the attacker discards the credentials entirely and replays the session cookie to be logged in as the user. TOTP, SMS, and push approvals are all equally useless against this, because the user genuinely produced a valid factor — it was just harvested in transit along with the session.
Push-bombing, or MFA fatigue. Where the attacker already has the password, they trigger the legitimate “approve this login?” push repeatedly, sometimes dozens of times, sometimes at three in the morning, occasionally paired with a phone call or message impersonating IT. The goal is a single moment of annoyance or confusion in which the user taps approve to make it stop. This is what breached Uber.
SIM swap and SS7 interception. SMS as a transport was never designed to be secure. An attacker who social-engineers or bribes a carrier into porting the victim’s number to a new SIM receives all their SMS codes directly; the SS7 signaling network underneath telephony has separately documented interception weaknesses. This falls SMS specifically and is why SMS is the weakest mainstream factor.
| Factor | Stops credential stuffing | Stops real-time AiTM phishing | Stops push-bombing | Stops SIM swap |
|---|---|---|---|---|
| Password only | No | No | — | — |
| SMS OTP | Yes | No | — | No |
| TOTP app | Yes | No | — | Yes |
| Push approval | Yes | No | No | Yes |
| Push + number matching | Yes | No | Yes | Yes |
| FIDO2 / WebAuthn (passkey, security key) | Yes | Yes | Yes | Yes |
| PIV / smartcard (PKINIT) | Yes | Yes | Yes | Yes |
The single column that matters in 2026 is “stops real-time AiTM phishing,” because that is the technique that industrialized. Only the bottom two rows say yes, and they say yes for the same reason.
The 2022 Field Test: Twilio, Uber, and the Cloudflare Counterexample
What makes the argument airtight is that 2022 ran the experiment for us, with the same attacker hitting different defenses.
A smishing campaign that Group-IB later named 0ktapus — the work of a crew overlapping with what is now tracked as Scattered Spider — sent SMS messages to employees at roughly 130 organizations, directing them to convincing fake Okta login pages. The pages harvested credentials and one-time codes in real time and relayed them to the operators. Twilio confirmed in August 2022 that employees had been phished this way, giving attackers access that rippled outward — including exposure of data for users of Signal, which relied on Twilio. The campaign worked because the second factor in use was a one-time code that the employee typed into a page the attacker controlled, and a typed code is a bearer token.
Uber fell in September 2022 to the other technique. An attacker affiliated with Lapsus$ obtained a contractor’s VPN credentials, then bombarded the contractor with MFA push notifications. When that alone did not work, they messaged the contractor on WhatsApp claiming to be Uber IT and instructed them to accept the prompt to make it stop. One approval was enough. Inside the network the attacker found PowerShell scripts containing hardcoded administrative credentials for a privileged-access management system, and from there reached Uber’s AWS, Google Workspace, and internal tooling. Push approval is a bearer token too; it just gets delivered by a tap instead of a keystroke.
Now the counterexample, and it is the cleanest A/B test the security industry has. Cloudflare was hit by the same 0ktapus campaign at the same time, with the same convincing fake-Okta pages. Three employees fell for it and entered their credentials and their TOTP codes into the attacker’s page — the identical human failure that breached Twilio. And the attack failed anyway. Cloudflare required FIDO2 hardware security keys, and while the attacker now held valid credentials and a valid TOTP code, they had no valid security-key assertion for the real Cloudflare origin and no way to produce one. The phishing site could relay passwords and typed codes, but it could not relay a cryptographic signature that the user’s authenticator refused to generate for the wrong domain. Same attacker, same kit, same human error — and the breach happened where the factor was phishable and died where it was not.
Why Origin Binding Is the Whole Game
The property that saved Cloudflare is origin binding, and it is worth being precise about because it is the entire reason FIDO2 belongs in a category by itself.
When a site registers a WebAuthn credential, that credential is scoped to the site’s domain — its relying-party ID. On every subsequent login the browser will only release a credential to a page whose origin actually matches that scope, and the authenticator signs a challenge together with a hash of that origin. A signature produced for login.evil.com is mathematically not a valid signature for okta.com, and the user’s authenticator will not even offer the okta.com credential to a page served from evil.com. The browser does the origin check and the authenticator does the binding; the human is removed from the part of the transaction they kept getting wrong. An AiTM proxy cannot fix this by relaying, because the thing it would need to relay — a valid assertion for the real origin — never gets produced. The user cannot be tricked into generating it, and the proxy cannot forge it without the private key it does not have.
TOTP / PUSH (phishable bearer token)
User --creds + OTP / tap--> [ Evilginx proxy ] --relays--> Real IdP
| captures session cookie
v
Attacker replays cookie ==> logged in as user
FIDO2 / WEBAUTHN (origin-bound assertion)
User --> [ proxy at login.evil.com ] --> Real IdP
^ browser asks authenticator for a credential
scoped to "login.evil.com" -> none exists
(assertion would be bound to evil origin -> rejected by IdP)
==> no valid assertion is ever produced. Attack dies here.
This is the same cryptography that powers passkeys; the mechanics of the registration and authentication ceremonies are covered in depth in Passkeys and FIDO2 Explained and the developer-side implementation in Passkeys and WebAuthn in Practice. The point for a threat model is narrower: TOTP, SMS, and push have no awareness of the origin requesting them, so the human becomes the transport and can be misdirected. FIDO2 makes the origin part of the signed material, so misdirection produces nothing usable. That is not a better speed bump. It is a different category of control.
The SMS Deprecation Story
SMS deserves its own paragraph because it is simultaneously the most-deployed second factor and the worst. NIST flagged the problem early: in the 2016 draft of SP 800-63B it proposed deprecating SMS as an out-of-band authenticator, and while the backlash softened “deprecated” into “restricted,” the direction never reversed. The current revision of the digital identity guidelines still treats authentication over the public telephone network as a restricted mechanism, requires relying parties to warn users about its risks, and elevates phishing resistance to a named, defined property that the strongest assurance levels expect.
The reasons are concrete. The SS7 signaling network that routes SMS has documented interception weaknesses that nation-state and criminal actors have both exploited. SIM-swap fraud — porting a victim’s number to an attacker-controlled SIM through social engineering or insider bribery — is a thriving criminal service, and it hands over every SMS code the victim would have received. And SMS shares the fundamental flaw of all one-time codes: even when delivered to the right phone, the code is a bearer token a user can read into a phishing page. SMS persists anyway because it has unmatched reach and the lowest possible enrollment friction, and a population that uses SMS MFA is unambiguously safer than one using passwords alone. But “better than nothing” is the ceiling of its value, and any account that matters should treat SMS as a recovery path of last resort, not a primary factor.
Deploying Phishing-Resistant MFA Without Breaking Everyone
Knowing FIDO2 is the answer does not make the rollout trivial, and the failure modes of a rollout are predictable. The practical sequence that works:
Enforce phishing resistance where the blast radius is largest first. You do not have to convert the entire workforce on day one. Identity platforms now express this directly as an authentication strength policy: in Microsoft Entra ID you require the “Phishing-resistant MFA” strength on privileged roles via Conditional Access; in Okta you require FastPass or a WebAuthn factor and disable the phishable ones for admins; Google offers Advanced Protection for high-risk accounts. Start with administrators, finance, and anyone who can reach production, because that is where an AiTM compromise becomes a company-ending event.
Issue hardware keys for the workforce and use platform passkeys for everyone else. A pair of FIDO2 security keys per employee — a YubiKey 5 or Bio, with a spare — is the gold standard for staff with real privilege; platform passkeys on managed devices cover the broad population at lower cost. The hardware-key workflow for SSH, sudo, and signing is covered in the YubiKey for SSH, GPG, and sudo guide. On Linux you can gate sudo and PAM logins on a FIDO2 key directly:
|
|
Treat number matching as a stopgap, not a destination. If you cannot get phishing-resistant factors everywhere immediately, enabling number matching on push (the user types a number shown on the login screen rather than blindly tapping approve) kills naive push-bombing. Be honest about its limit: it stops the fatigue attack but not AiTM, because a proxy can simply display the real number to the victim. It buys time. It does not close the gap.
Harden account recovery, because that is where the attacker pivots next. The most common way phishing-resistant MFA gets defeated is not by beating the crypto; it is by attacking the recovery flow — the “lost my key” path that often falls back to email, SMS, or a help-desk call. Register at least two FIDO2 authenticators per account so loss is not a crisis, secure the help-desk verification process against social engineering (the Scattered Spider crews are expert at it), and never let the recovery path be weaker than the primary factor it restores.
The destination state is a simple policy: for anything that touches money, infrastructure, or sensitive data, the only acceptable factors are FIDO2/WebAuthn or PIV smartcards, SMS is disabled, push is allowed only with number matching as a transitional courtesy, and every privileged account has redundant hardware keys with a hardened recovery path. This aligns with what zero-trust architecture in practice assumes about identity as the new perimeter: if the credential can be phished, every downstream control inherits that weakness.
Verdict
The history of MFA is the history of a control that worked beautifully against the threat it was designed for and then watched the threat evolve out from under it. Against bulk credential stuffing, any second factor is decisive, and that is reason enough to have MFA on every account you own. Against a present, motivated attacker running a real-time phishing proxy, most second factors are theater: TOTP codes, SMS codes, and push approvals are all bearer tokens with no idea who is asking for them, and the user is a transport that can be redirected. Push-bombing and SIM-swapping are simply two more ways to collect the bearer token. 2022 proved this at scale and, in the Cloudflare counterexample, proved the converse just as cleanly: the same attacker, the same phishing kit, and the same human error produced a breach where the factor was phishable and produced nothing where it was origin-bound.
The fix is not better user training, because Cloudflare’s employees failed the training exactly as Twilio’s did and it did not matter. The fix is to remove the human from the part of the transaction they reliably get wrong, by binding the second factor to the website’s cryptographic identity so that misdirection yields nothing usable. In practice that means FIDO2 and WebAuthn — passkeys and hardware security keys — with PIV smartcards as the equivalent in regulated environments. Deploy it on your privileged accounts first, issue redundant hardware keys, disable SMS, treat number matching as a temporary courtesy rather than a solution, and harden the recovery flow that attackers will pivot to once the front door holds. Phishing-resistant MFA is no longer the premium tier of authentication. For anything worth protecting, it is the only tier that is not already living on borrowed time.
Sources
- CISA: Implementing Phishing-Resistant MFA (fact sheet)
- NIST SP 800-63B — Digital Identity Guidelines: Authentication
- Group-IB: the 0ktapus phishing campaign
- Twilio: incident report on the August 2022 social-engineering attack
- Cloudflare: “The mechanics of a sophisticated phishing scam and how we stopped it”
- Uber: security update on the September 2022 breach
- FIDO Alliance: WebAuthn and CTAP specifications overview
- W3C Web Authentication (WebAuthn) Level 2 specification
- Microsoft Entra: authentication strengths and phishing-resistant MFA
- pam-u2f — FIDO2/U2F PAM module (Yubico)
Comments