TOTP fixes the channel, not the credential
TOTP kills SMS interception and SIM-swap OTP theft, but AiTM phishing still steals the session token. What TOTP secures and what it doesn't.
TOTP is RFC 6238. Six digits, HMAC-SHA1 computed over a shared secret and a Unix timestamp floored to a 30-second step. The secret is provisioned once, usually through an otpauth:// URI encoded in a QR code, base32-encoded, then held on the authenticator device. Both endpoints compute the same HMAC independently. No network round trip at generation time. That property is why security teams moved off SMS. It is also why the migration solves less than the trend on infosec.exchange implies.
SMS-based 2FA failed at the delivery channel. The code travels over the carrier network in cleartext. SS7 signalling authenticates nothing between interconnect partners, so an attacker with SS7 access reroutes the message or reads it in transit. SIM swap is the cheaper path. Social-engineer the carrier retention desk, port the number to an attacker-controlled SIM, receive every code sent afterward. Both attacks target the transport, not the user. MITRE tracks the SIM-swap variant under T1451. The code was never the weak point. The channel was.
TOTP removes the channel. The secret never transits after provisioning. There is no message to intercept and no number to port. An attacker holding SS7 access gets nothing from a TOTP account. Against SIM swap and SS7 interception, TOTP is a hard control. The advisories pushing the migration are correct on that narrow claim, and only that claim.
The residual is structural. TOTP is a bearer credential typed into a form. A user reads six digits off a device and enters them into a login page. The authenticating endpoint cannot tell whether those digits came from the legitimate device or were relayed by something sitting in the path. TOTP proves possession of the shared secret at one instant. It proves nothing about who occupies the network path between the user and the real server.
The 30-second window widens that gap. Most validators accept the current step plus one step of clock skew on either side, so a given code stays valid for up to 90 seconds in practice. Many implementations never mark a consumed code as spent, so the same six digits validate more than once inside the window. An attacker relaying in real time operates comfortably inside that budget. The replay tolerance built in for usability is the same tolerance an interception attack needs.
That path is where the pivot happens. After a phishing lure lands under T1566, the victim reaches a reverse proxy the attacker controls. The proxy is not a static clone of the login page. It is a live relay. It forwards the victim’s requests to the real identity provider and forwards the genuine responses back. The victim sees the authentic login flow because it is the authentic flow, proxied. Username, password, and TOTP code pass through the proxy in real time. The proxy submits the TOTP to the real endpoint inside its validity window. Authentication succeeds. This is adversary-in-the-middle, T1557.
The transport gives the victim no warning. The phishing domain carries a valid TLS certificate, usually a free Let’s Encrypt one issued minutes earlier, so the browser padlock renders normally. TLS terminates at the proxy. The proxy decrypts, reads the credentials and the code, then re-encrypts to the real origin over its own TLS session. The lock icon confirms the connection to the proxy is encrypted. It says nothing about who terminates it. Certificate transparency logs record the newly issued cert, which is one of the few pre-compromise signals available to a defender watching for lookalike domains.
Then the theft. On successful authentication the identity provider issues a session token, a cookie or a SAML assertion or an OAuth refresh token. HTTP is stateless, so that token becomes the bearer credential for every request after login. The proxy sits in the exact position to read it. The attacker captures the session cookie as it transits back toward the victim. T1539, steal web session cookie. From that point the attacker replays the cookie from their own infrastructure and holds an authenticated session. No password prompt. No second TOTP challenge. The MFA event already completed and will not repeat until the token expires. The token carries the authentication forward, and it has no cryptographic binding to the device that earned it. Forging or replaying that web credential maps to T1606.001.
The mechanism is not theoretical. The 0ktapus campaign, tracked by Group-IB and called Scatter Swine elsewhere, ran this against more than a hundred organisations in 2022. The kit harvested credentials and one-time codes through AiTM proxies and pushed them to a Telegram channel. Twilio was breached through it. Cloudflare was hit by the same wave and was not compromised, because the targeted accounts required FIDO2 hardware keys that do not relay. The origin binding failed at the proxy. Same campaign, same lure, different second factor, opposite outcome. That delta is the entire lesson.
Microsoft Threat Intelligence has tracked AiTM phishing at scale, reporting campaigns against more than 10,000 organisations and follow-on business email compromise run by clusters such as Storm-1167. The pattern after token theft is consistent. The attacker imports the stolen session, enumerates mailbox rules, sets a hidden forwarding or delete rule, and runs financial fraud from an account that MFA marks as fully authenticated. The second factor did its job at login and became irrelevant one request later.
Tooling is public. Evilginx and Modlishka are the reference AiTM reverse-proxy frameworks. Commercial phishing-as-a-service kits such as EvilProxy package the same relay model with hosting and OTP capture included. Infostealers are the second supply line. Lumma, RedLine, and StealC skip the proxy entirely and lift session cookies straight from the browser credential store on an already-compromised host, decrypting the Chromium Login Data and Cookies stores through DPAPI on Windows. The end state is identical to the AiTM path. A valid session token in attacker hands. Okta has published repeatedly on session-token theft against its own sign-in flows. The attack depends on no Okta-specific flaw. It depends only on the bearer nature of the token.
In telemetry the successful login reads clean. The identity provider logs a successful sign-in with MFA satisfied, because MFA was satisfied. The TOTP validated. Entra ID sign-in logs record authenticationRequirement as multiFactorAuthentication with result success. Nothing in that record separates the proxied session from a legitimate one at the moment of authentication. The available signal is downstream and probabilistic. Impossible travel between the victim geolocation and the replay origin. ASN mismatch, a residential IP at login against a hosting-provider ASN on the replayed session. User-agent drift between the authentication event and later requests. A session token surfacing from an IP the account has never used. These are correlation signals, not deterministic ones, and they fire after the session is already live.
What does not fire matters more. Cookie replay against a valid unexpired session generates no failed-auth event, no MFA prompt, no lockout. To the application the request carries a legitimate token. SIEM rules keyed on failed logins, password spray, or repeated MFA challenges see nothing, because none of those events occur. On the infostealer host, an EDR may catch the stealer process opening the browser Cookies file, a Sysmon Event ID 11 file access or a process reading another process memory, but that requires the endpoint to be instrumented and the behaviour to be flagged before exfiltration. The detection gap is fixed by design. A stolen bearer token is indistinguishable from a legitimate one until behavioural context contradicts it. access not constrained at runtime evaluation narrows the window by re-checking session conditions mid-stream, but only where the identity provider and the application both honour it.
Detection has to move to the session layer, because the authentication layer already passed. The useful signals are token reuse from a second IP or ASN, refresh-token activity from a device with no matching sign-in, and mailbox or admin actions immediately following a sign-in from an unfamiliar network. Response is revocation, not a password reset. Killing the refresh token and forcing re-authentication ends the hijacked session. A password change alone does not, because the live session token does not depend on the password once issued.
The patch boundary is precise. Moving from SMS to TOTP closes SS7 interception and SIM-swap code theft. Those attacks are dead against a TOTP secret. Everything downstream of the login form is unchanged. AiTM relay, session-cookie theft, and token replay work identically against SMS and TOTP, because both are shared-secret codes typed into a page and neither binds to the origin the browser is actually talking to.
What breaks the chain is origin binding. WebAuthn and FIDO2 sign an authentication challenge scoped to the real relying-party origin. A proxy serving a different domain cannot produce a valid assertion, because the origin in the signed data does not match the origin the authenticator was registered against. The relay fails at the exact point a TOTP passes through untouched. Token binding and DPoP extend the same principle to the session layer, tying the issued token to a private key the client holds so that a lifted cookie is inert off the original device.
TOTP is a correct fix for the attack it addresses. It is not a fix for phishing, and it was never specified to be one. Retiring SMS as a second factor is worth doing on its own terms. Reading TOTP as protection against session hijacking is a category error. The residual exposure is the session token, and the session token does not care which kind of code unlocked it.
See also: NordVPN for tunneled traffic when operating outside controlled networks.
#ad Contains an affiliate link.
Keep Reading
session hijackingMFA protects the login, not the session.
Fastpotify mints unbound session cookies that survive MFA. Stolen via AiTM or infostealer, they replay as full sessions. The telemetry that catches it.
passkeysThe attacker skips your login and steals the cookie
Passkeys defeat credential phishing but not session hijacking. How token replay, passkey enrollment, and weak recovery bypass phishing-resistant MFA.
MCPZero-Touch OAuth strips the 2025-06-18 MCP mandate
Zero-Touch OAuth for MCP fails as a trust-on-first-use design: unauthenticated dynamic client registration and unbound bearer tokens enable session hijack.
Latest on the Wire
Full wire →- 17 Years Frozen in Street View: A Tokyo Car Outlived the House It Sat BesideHacker News
- A distributed-systems veteran wrestles with McKenney's parallel programming bibleHacker News
- AI agents resorted to hacking public data sites to finish routine tasksHacker News
- California's billionaire wealth tax will fail because billionaires can move — the land can'tHacker News
New signal daily · RSS
Stay in the loop
New writing delivered when it's ready. No schedule, no spam.