Skip to content
AccessLens

Security Tips

Adversary-in-the-Middle: When the Stolen Token Is the Whole Attack

Adversary-in-the-middle lets the user sign in to the real service, then steals the session token it hands back. MFA and device compliance already passed, so replay walks straight through. Here are the Conditional Access controls that make a stolen token useless, and how AccessLens checks you actually have them.

Stephen Devlin · · 9 min read

Device code phishing gets an attacker a session by convincing a user to authorise the wrong device. Adversary-in-the-middle takes a different route to the same destination. It lets the user sign in to the real service, then steals the session token that the service hands back. In both cases the password and the MFA challenge are working exactly as designed. The attacker is not defeating authentication. They are walking off with the result of it.

This is the follow-up to the device code post, and it is the second entry in a short series on token theft. The common thread is simple and uncomfortable: modern attacks increasingly ignore your credentials and target your tokens. Microsoft's own telemetry puts the scale in perspective. AiTM activity is up sharply year on year, with token replay detections more than doubling and infostealer-sourced tokens making up a growing share.

The good news is that Conditional Access has caught up. There is now a set of controls built specifically to make a stolen token useless the moment it leaves the device it was issued to. This post walks through how the attack works, why some of your existing defences do and do not help, and the exact policies that close the replay window.

How the Attack Works

An adversary-in-the-middle attack puts a reverse proxy between the victim and the genuine login page. The victim clicks a link, lands on attacker-controlled infrastructure, and sees what looks like the Microsoft sign-in experience. It looks right because it is real. The proxy is relaying every request to Microsoft and every response back to the victim in real time.

The victim enters their password. The proxy forwards it. Microsoft issues an MFA challenge. The proxy forwards that too. The victim approves the push or types the code. Microsoft is satisfied and issues a session token. That token is the prize, and the proxy is sitting directly in its path.

Adversary-in-the-Middle Token Theft
A real sign-in, relayed through a proxy that keeps the token.
01
The lure lands the victim on a proxy
A phishing link points at attacker infrastructure, not Microsoft.
The real login page is relayed
Every request and response passes through the attacker in real time.
02
03
The victim completes MFA
Password and second factor succeed against the genuine service.
The proxy captures the session token
The token that proves the completed sign-in is intercepted in transit.
04
05
The attacker replays it from their own device
The stolen token is presented from attacker infrastructure and accepted.

Tooling for this is mature and widely available. Reverse-proxy phishing kits automate the relay, harvest the token, and in some cases register a passkey or authentication method on the account before the operator has even logged in. There is also a second, quieter delivery path that skips the proxy entirely: infostealer malware pulls session tokens straight out of a browser profile on an already-compromised endpoint. Either way, the end state is the same. A valid token, minted by a genuine and fully-authenticated sign-in, is now in the attacker's hands.

Proof of Concept: Reproducing AiTM in an Isolated Lab

The most convincing way to understand this attack, and to prove your controls actually stop it, is to run it end to end in a lab you own. Everything below was carried out in a dedicated test tenant against test accounts I control. The exercise has two halves. First, reproduce the attack against a tenant whose only control is "require MFA" and watch it succeed. Then turn the replay controls on and watch each one break the attack at a specific stage.

Scope and authorisation. Run this only in a separate, non-production Entra tenant, against throwaway test users, on infrastructure you own. Reverse-proxy phishing is illegal when pointed at people who have not consented. Do not target real employees, a production tenant, or any identity you are not explicitly authorised to test. Keep the lure domain off public indexing, tear it down when you are finished, and if the work is for a client, get written authorisation first. The goal here is defensive validation, not access.

The lab

  • An isolated Microsoft Entra test tenant, licensed for the features under test (Entra ID P2 for risk-based policy, Global Secure Access for the compliant network check).
  • A test user with MFA registered, standing in for the victim.
  • A reverse-proxy phishing host on a VM you control, running a current AiTM toolkit with the standard Microsoft 365 phishlet and a throwaway domain. The Evilginx family is the common public choice.
  • A separate clean machine or browser profile as the attacker replay host, with no prior session to the tenant.

Step 1: Stand up the reverse proxy

Point the lure domain at the proxy, load the Microsoft 365 phishlet, and generate the lure URL. At this stage the proxy is ready to relay the genuine login experience while recording everything that passes through it.

Lab screenshot
The proxy console with the Microsoft 365 phishlet enabled and the generated lure URL.
/blog/aitm-01-proxy-setup.png

Step 2: Walk the victim through a normal sign-in

From the victim account, open the lure link. The page presented is Microsoft's real sign-in, relayed through the proxy. Enter the password and complete MFA exactly as the user normally would. From the victim's point of view nothing is unusual: the sign-in succeeds and lands on the expected application.

Lab screenshot
The proxied Microsoft 365 login as the victim sees it, with the lure domain in the address bar.
/blog/aitm-02-victim-signin.png

Step 3: Harvest the session

Back on the proxy, the completed authentication is captured, including the session cookies that represent the post-MFA session. This is the whole prize. No password cracking, no MFA bypass, just the artefact the successful sign-in produced.

Lab screenshot
The captured session and cookies for the test user in the proxy console.
/blog/aitm-03-captured-session.png

Step 4: Replay from the attacker host

Import the captured session into the clean browser on the attacker host and load the mailbox or portal. Access is granted with no password prompt and no MFA challenge, because the token already carries proof that both were satisfied. This is the moment the earlier theory becomes concrete: a valid token, replayed from an unrelated machine, is accepted.

Lab screenshot
The victim's mailbox open on the attacker host, reached with the replayed session and no MFA prompt.
/blog/aitm-04-replay-success.png

At this point the attack is proven against a tenant whose only control was "require MFA". The stolen session works from a machine that never authenticated. The next sections explain the controls that change this outcome, and then Part Two repeats the lab with each one enabled.

Why a Valid Token Beats Most of Your Existing Policy

The reason this is so effective is structural. A Conditional Access policy is evaluated at the moment of authentication. Once a token is issued, it already carries proof that MFA was satisfied and that the sign-in met your device and location conditions at that instant. Replaying that token later, from a different machine, does not re-run those checks. The conditions were true when the token was minted, and the token is the receipt.

That is the trap in a policy set that looks complete on paper. Require MFA, require a compliant device, block legacy authentication: all sensible, and none of them re-evaluated on a token that was issued to a legitimate user who genuinely passed them. The attacker is not trying to pass your controls. They are borrowing a token that already did.

So the question is not "how do I make authentication stronger." The user authenticated correctly. The question is "how do I make this token refuse to work anywhere except the device it was born on."

Where Phishing-Resistant MFA Does and Does Not Help

It is worth being precise here, because the honest answer is different from the device code post.

Against the proxy variant of AiTM, phishing-resistant MFA is a genuine prevention, not just a mitigation. FIDO2 security keys and passkeys are origin-bound. The authenticator will only complete its ceremony for the real Microsoft origin, and a reverse proxy sitting on a look-alike domain is not that origin. The ceremony fails, no token is issued, and there is nothing to steal. If you take one deployment action away from this post, making phishing-resistant methods the default for your workforce is the highest-value one.

The important caveat is that origin binding protects the sign-in, not the token afterwards. If the token is stolen a different way, for example by an infostealer lifting cookies from a browser on a compromised laptop, the strength of the original MFA method is irrelevant. The sign-in already happened correctly. This is why phishing-resistant MFA and the replay controls below are complementary rather than alternatives. One stops the proxy from ever getting a token. The other stops any stolen token from being usable elsewhere.

The Controls That Make a Stolen Token Useless

Microsoft groups token defence into three jobs: minimise the chance of theft, detect and mitigate theft that happens, and protect against replay. Prevention through phishing-resistant MFA and device hardening is the first job. The controls below are the third, and they are the ones that specifically defeat replay.

1. Token Protection (token binding)

Token Protection cryptographically binds a sign-in session token to the device it was issued on. The binding uses the device's Primary Refresh Token, whose secret is held in hardware such as the TPM on Windows. A bearer token lifted off that device and replayed elsewhere no longer satisfies the binding, so Entra rejects it. This is the strongest of the replay controls because the token is simply unusable off-device.

The trade-off is scope. At the time of writing, Token Protection for sign-in sessions covers Windows native applications connecting to Exchange, SharePoint, and Teams. It requires a registered or joined device, because there is no PRT to bind to otherwise, and it only protects the user actually signed in to that device. Treat it as a high-value control for your Windows fleet and your most sensitive workloads, deployed in report-only first, rather than a single switch that covers everything.

The Conditional Access shape is a session control:

  • Users: all users, with emergency-access exclusions
  • Target resources: Exchange Online and SharePoint Online (Teams rides on these)
  • Session: Require token protection for sign-in sessions
  • Initial state: Report-only

2. Compliant Network check via Global Secure Access

Token Protection is narrow but absolute. The Compliant Network check is broad but network-based, and the two are designed to be layered. It uses Global Secure Access as a network signal and requires that token requests originate from a device connected to your tenant's Global Secure Access service.

The mechanics are what make it effective against replay. Entra performs authentication-plane enforcement at sign-in, so if an attacker requests a fresh access token using a stolen refresh token from a device that is not on your compliant network, the request is denied outright. For applications that support Continuous Access Evaluation, such as Microsoft Graph, there is also data-plane enforcement: a stolen access token replayed from outside the compliant network is rejected by the application in near-real time, rather than remaining valid for its full 60 to 90 minute lifetime.

Two details make this practical to run. It is tenant-specific, so a compliant-network token from another tenant cannot satisfy yours, and it removes the old burden of maintaining egress IP lists because the signal comes from the Global Secure Access client rather than a named IP range.

The policy shape blocks everywhere except the compliant network:

  • Users: all users, with emergency-access exclusions
  • Target resources: all resources (exclude Microsoft Intune and Intune Enrollment to avoid a circular dependency during device onboarding)
  • Network: include Any location, exclude All Compliant Network locations
  • Grant: Block access

Global Secure Access resources are excluded automatically when Compliant Network is enabled, so you do not add those by hand.

3. Continuous Access Evaluation, so revocation actually lands

Both controls above lean on Continuous Access Evaluation to close the gap between "we detected a problem" and "the token stopped working." Without CAE, a revoked or risky session can keep functioning until the access token expires. With CAE, supported applications re-evaluate critical events in near-real time and redirect the client back to Entra to reauthenticate.

CAE is what turns a risk detection into an actual block mid-session. If Identity Protection raises the user to high risk because a token is being replayed with unfamiliar properties, a CAE-capable application revokes access almost immediately rather than at the next hourly refresh. Make sure CAE is enabled and paired with a risk-based policy, covered next.

4. Risk-based Conditional Access as the detection-driven backstop

Token Protection and Compliant Network prevent replay in the scenarios they cover. Risk-based Conditional Access catches the rest. Identity Protection includes detections aimed squarely at this attack, including Anomalous Token, Attacker in the Middle, and Unfamiliar sign-in properties. When a replayed token trips one of these, a risk policy can demand interactive, phishing-resistant reauthentication.

  • Users: all users, with emergency-access exclusions
  • Condition: Sign-in risk, medium and above
  • Grant: Require authentication strength (phishing-resistant MFA)
  • Session: Sign-in frequency, every time

Because the attacker holds a token but not the phishing-resistant credential or the physical key, the demand to reauthenticate interactively is where the borrowed token finally fails.

Proof of Concept, Part Two: Watching the Controls Defeat It

Now re-run the same lab with the controls above enabled, one variable at a time, so you can see exactly which stage each one breaks. Running them individually is the useful part. It shows that different controls intervene at different points in the attack.

Phishing-resistant MFA breaks the proxy at sign-in

Register a FIDO2 key or passkey for the victim and require phishing-resistant authentication strength, then repeat Step 2. The authenticator refuses to complete its ceremony because the origin presented by the proxy is not the real Microsoft origin. No token is ever issued, so there is nothing for the proxy to capture. The attack ends before Step 3.

Lab screenshot
The passkey ceremony failing to complete through the proxy origin, with no session issued.
/blog/aitm-05-fido2-blocks.png

Compliant Network rejects the replay

Leave password-plus-MFA in place, enable Global Secure Access signalling, and apply the compliant-network block policy. This time the proxy still captures a session in Step 3, but the replay in Step 4 fails. When the attacker host, which is not on your compliant network, presents the stolen token, Entra denies the request. The captured session is inert off your network.

Lab screenshot
The "You can't access this right now" compliant-network block when the replay is attempted off-network.
/blog/aitm-06-compliant-network-block.png

Token Protection binds the token to the device

On a registered Windows device, apply the token protection session policy for Exchange and SharePoint. A session token bound to that device's Primary Refresh Token cannot be replayed elsewhere. Lifting it to the attacker host and presenting it fails the binding check, and Entra rejects it.

Lab screenshot
The token protection failure in the Entra sign-in log when the bound token is replayed off-device.
/blog/aitm-07-token-protection-block.png

Read together, the two halves of the lab make the layering argument concrete. Phishing-resistant MFA prevents the theft in the proxy scenario, while compliant network and token protection neutralise the token even when theft succeeds through another path such as an infostealer. One control stops the proxy from getting a token at all. The others stop any stolen token from working somewhere else.

Detecting Replay After the Fact

Prevention aside, you want a signal when a token is used somewhere it should not be. The classic tell is the same session appearing from two very different contexts in a short window. A starting point in Log Analytics or Sentinel, to be tuned to your environment:

SigninLogs
| where TimeGenerated > ago(1d)
| summarize
    Locations = make_set(Location),
    IPs = make_set(IPAddress),
    UserAgents = make_set(UserAgent),
    SignInCount = count()
    by UserPrincipalName, CorrelationId
| where array_length(IPs) > 1
| where array_length(Locations) > 1
| sort by SignInCount desc

This is a hunting query, not a finished detection. Impossible-travel and infrequent-country analytics from Defender for Cloud Apps, plus the built-in Anomalous Token and Attacker in the Middle risk detections, are more reliable at scale. The point of the query is to make the shape of replay concrete: one authenticated identity, one correlated session, two places at once.

Where AccessLens Fits

None of the controls in this post live in AccessLens. Entra issues and binds the tokens, and Entra enforces the policies. AccessLens answers a narrower question: does your tenant actually have these replay controls, are they scoped the way you assume, and can you enable them without breaking a legitimate workflow. A tenant can require MFA everywhere and still have no token-protection, compliant-network, or risk-based policy at all, and that gap is easy to lose in a long policy list.

Gap Analysis flags the missing replay controls with their target policy shape, the policy views expose the exclusions and report-only states that quietly weaken them, and the What-If Simulator lets you model the compliant-network or token-protection change before you enforce it. It is a way to confirm the lab result holds in your real tenant, not a replacement for the Entra controls themselves.

A Practical Rollout

I would sequence this in five passes:

  1. Prevent at the front door first. Make phishing-resistant MFA the default authentication strength for the workforce. This alone removes the proxy variant of AiTM for anyone using it.
  2. Turn on the replay controls in report-only. Enable Global Secure Access signalling and build the Compliant Network block policy in report-only. Build the Token Protection session policy for Exchange and SharePoint, also report-only. Enable CAE.
  3. Model and validate. Use AccessLens What-If for representative scenarios, confirm Gap Analysis shows the intended coverage, and compare against Entra report-only events. Confirm Intune enrollment exclusions are in place so device onboarding does not deadlock.
  4. Add the risk-based backstop. Deploy the sign-in-risk policy requiring interactive phishing-resistant reauthentication at medium risk and above.
  5. Enforce and monitor. Move policies from report-only to on once expected access is accounted for. Alert on token anomalies, impossible travel, and the Attacker in the Middle and Anomalous Token risk detections. Keep emergency-access accounts excluded and monitored throughout.

If you confirm a token has been stolen, a password reset is not enough. Revoke the user's sessions and refresh tokens, review registered devices and newly added authentication methods, check for malicious inbox rules, and audit activity performed through Microsoft Graph. The visible phishing moment can be brief while the stolen token's access persists.

The Real Lesson

Device code phishing and adversary-in-the-middle look like different attacks, and technically they are. One authorises the wrong device, the other steals the token from the right one. But they teach the same lesson, which is why they belong in the same series. Authentication strength answers who is signing in. It does not, on its own, answer whether the token that sign-in produced can be replayed by someone else, somewhere else.

The controls that answer that second question now exist and are worth deploying deliberately: phishing-resistant MFA to stop the proxy getting a token at all, Token Protection to bind tokens to their device, Compliant Network to reject tokens used off your network, and CAE with risk-based policy to make revocation land while it still matters. Find out which of them your tenant is actually running, in report-only first, and close the replay window before someone else finds it open.

Check your tenant. AccessLens analyses your Microsoft Entra Conditional Access policies, flags missing token-protection, compliant-network, and risk-based replay controls, surfaces the exclusions that weaken them, and lets you model the change before enforcement. Try AccessLens and check whether your tenant can survive a stolen token.

Sources

Share this post
LinkedIn