HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
AI AIAiTMConditional AccessAuthentication StrengthPhishing-ResistantEntra IDMicrosoft GraphIdentity Protection

AI-Powered Phishing Doesn't Need to Beat MFA - It Just Needs Your Conditional Access Policy to Say "MFA" Instead of "Phishing-Resistant"

IA
Imran Awan
16 August 2026

Your users are getting better at spotting phishing. It does not matter anymore. The phishing kits attackers use today - Evilginx-style reverse proxies, sold as a service, wrapped around AI-generated pretexting that reads like it came from your actual finance director - do not ask the user to hand over a password in a form that gets typed into a spreadsheet somewhere. They sit between the user and the real Microsoft sign-in page, relay every keystroke and every one-time code in real time, and walk away with the live session token five seconds after the user finishes typing.

That token is not a password. Multifactor authentication (MFA) does not stop it, because MFA already ran - the user completed it, on the real Microsoft page, relayed through the attacker's proxy without either side needing to fake anything. The only thing that stops this is the shape of the authentication method itself: whether it can be relayed through a proxy at all. That is a Conditional Access configuration question, not a user-training question, and most tenants have never actually checked the answer.

The short version

Adversary-in-the-middle (AiTM) phishing kits relay a real sign-in session, including whatever MFA prompt the user completes, so any Conditional Access policy that only requires mfa or a mixed authentication strength (password+SMS, password+push, and so on) can be defeated by a convincing enough lure - and AI-generated pretexting makes the lure far more convincing. Only phishing-resistant methods - Windows Hello for Business, FIDO2 security keys, and Entra certificate-based authentication - are cryptographically bound to the real origin and cannot be relayed this way. Entra ID's built-in Phishing-resistant MFA strength authentication strength enforces exactly that, but it has to be explicitly selected in each policy's grant control - the generic Require multifactor authentication control does not upgrade itself. This post shows how to query every Conditional Access policy in your tenant via Microsoft Graph, tell which ones actually require phishing-resistant authentication versus which ones only require "MFA (any method)," and close the gap.

The problem: "Require MFA" and "Require phishing-resistant MFA" are not the same grant control

Open the Conditional Access policy list in the Entra admin center and most tenants have at least a handful of policies with a grant control that just says Require multifactor authentication. That looks like a strong control. It has been the recommended baseline for years. The problem is what "multifactor authentication" is allowed to mean.

A user who satisfies "Require multifactor authentication" (the mfa built-in grant control) can do it with a text message code, a phone call, a Microsoft Authenticator push notification, a software OATH token, or a hardware OATH token, in combination with a password. Every single one of those can be entered into, or approved from within, a phishing page that is relaying the real authentication flow. The policy is satisfied. The sign-in succeeds. The session token that comes back belongs to the attacker's browser, not the user's.

Entra ID has had a separate, more specific control since 2022: Require authentication strength, with a built-in option called Phishing-resistant MFA strength. It only accepts three method combinations: Windows Hello for Business (or platform credential), a FIDO2 security key, and Entra certificate-based authentication used as a multifactor method. None of the three can be relayed through a reverse-proxy phishing kit, because the cryptographic handshake is bound to the actual origin the browser is talking to - not to whatever origin the phishing page presents.

Gotcha: Enabling Windows Hello for Business in your tenant does not require anyone to use it. If the Conditional Access grant control still says mfa (not authenticationStrength), a user with WHfB registered can still complete sign-in with a push notification or an SMS code instead - and an AiTM kit will happily accept whichever one shows up.

The gap this post audits is specific: for every Conditional Access policy that actually grants access to a population of users, does its grant control reference an authentication strength whose allowed combinations are exclusively phishing-resistant - or does it only require generic MFA, or a strength that still allows a relayable combination like password+SMS alongside FIDO2? Most tenants have never run that query across their whole policy set. They have looked at one or two "sensitive" policies and assumed the rest follow the same pattern.

Why it happens: how AiTM relay actually defeats SMS, push, and OTP-based MFA

An adversary-in-the-middle (AiTM) phishing kit is a reverse proxy. The user's browser talks to the attacker's server, thinking it is talking to login.microsoftonline.com. The attacker's server, in turn, opens its own connection to the real Microsoft sign-in endpoint and relays everything back and forth in both directions, live. Microsoft's own write-up on a large-scale campaign using this technique - which used the Evilginx2 toolkit and targeted more than 10,000 organizations starting in 2021 - describes the mechanism directly: once the attacker's proxy captures the session cookie issued after a successful sign-in, "the attacker can inject it into their browser to skip the authentication process, even if the target's MFA is enabled."

Read that sentence again: even if MFA is enabled. The proxy does not need to defeat MFA. It relays MFA. The user gets the real SMS code, the real push notification, the real "approve this sign-in" prompt - because it genuinely is the real Microsoft authentication flow, just with an eavesdropper sitting in the middle of it. What the attacker walks away with is not a password. It is a valid session token, issued by the real identity provider, for the real user, at the moment the user finished authenticating.

Conceptual sequence — AiTM reverse-proxy relay
# 1. User clicks an AI-personalized phishing link in a convincing, context-aware lure
User Browser  ->  Attacker Reverse Proxy  ->  login.microsoftonline.com

# 2. User types their real password into what looks like the real sign-in page
Password ................. relayed straight through ................. accepted

# 3. Entra ID prompts for MFA. The proxy relays the prompt back to the user.
SMS code / push / OTPaccepted

# 4. Entra ID issues a real session token. The proxy captures it in transit.
Session token stolen  <-  captured by attacker's proxy  <-  token issued

# 5. Attacker replays the stolen token from their own browser. No password needed again.
Attacker signs in as the user — MFA already satisfied, nothing left to prompt for.

The part that has changed in the last two years is the lure quality, not the relay mechanism. Storm-1167 and the wave of AiTM kits that followed it (Tycoon2FA and similar phishing-as-a-service platforms are current examples Microsoft has documented) used generic bait: fake voicemail notifications, fake document-sharing emails. What gets a user to click today is increasingly AI-generated: pretexting drafted by a language model that reads their public LinkedIn activity and recent company news, and in the more advanced helpdesk social-engineering cases, a voice-cloned or deepfake-assisted phone call impersonating an executive or an IT technician requesting an MFA reset. Microsoft's own security blog has continued to track this category of attack, including a 2026 breakdown of the Tycoon2FA AiTM phishing-as-a-service platform and a multi-stage 2026 campaign that used a fake "code of conduct" pretext to drive victims to an AiTM kit.

Note: None of this requires a new authentication-bypass technique. Microsoft's guidance on this is explicit: Conditional Access authentication strength was designed for exactly this scenario, and it predates the current wave of AI-assisted phishing by several years. The gap is adoption, not availability.

A more convincing lure does not need a smarter exploit. It just needs to survive human suspicion for one extra click. Once the click happens, the outcome depends entirely on whether the authentication method behind it can be relayed - which is a tenant configuration fact, not a training outcome.

How to verify: reading grantControls.authenticationStrength via Microsoft Graph

Every Conditional Access policy is a conditionalAccessPolicy object in Microsoft Graph. Its grant control section is a conditionalAccessGrantControls object with two properties that matter here: builtInControls (a plain array that can contain the string "mfa" among other values) and authenticationStrength, a nested authenticationStrengthPolicy object that is only populated when the policy uses the newer "Require authentication strength" control.

Step 1 - read every policy in the tenant. This single call returns the full policy set with grant controls and, where used, the authentication strength expanded inline:

PowerShell 7 — list every Conditional Access policy
Connect-MgGraph -Scopes "Policy.Read.All"
$policies = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"
$policies.value | Select-Object displayName, state, @{n='grant';e={$_.grantControls.builtInControls -join ','}}, @{n='strength';e={$_.grantControls.authenticationStrength.displayName}}

What good looks like: a policy targeting a sensitive app or an admin role shows strength = Phishing-resistant MFA strength (or a custom strength you built the same way). What a gap looks like: grant = mfa with an empty strength column - that policy accepts any registered MFA method, full stop.

The built-in authentication strengths are documented with their exact allowed combinations. Microsoft's own example response for a policy using the built-in "Multifactor authentication" strength (not the phishing-resistant one) shows the full combination list, and it is worth reading closely because it explains exactly why generic MFA is not enough:

Microsoft Graph response — grantControls.authenticationStrength.allowedCombinations (built-in "Multifactor authentication" strength)
"windowsHelloForBusiness" ← phishing-resistant
"fido2" ← phishing-resistant
"x509CertificateMultiFactor" ← phishing-resistant
"password,microsoftAuthenticatorPush" ← relayable by AiTM
"password,sms" ← relayable by AiTM
"password,voice" ← relayable by AiTM
"password,softwareOath" ← relayable by AiTM

This is the built-in Multifactor authentication strength itself, documented by Microsoft with the ID 00000000-0000-0000-0000-000000000002. It is a superset that includes the three phishing-resistant methods alongside the relayable ones. Selecting "Require authentication strength › Multifactor authentication" in the portal is barely different from selecting "Require multifactor authentication" directly - both accept the weakest method a user has registered. Only the Phishing-resistant MFA strength built-in policy, or a custom strength you scope down yourself, actually closes the gap.

Watch out: A custom authentication strength that includes FIDO2 and password+SMS "as a fallback for users without a key yet" is not phishing-resistant. It is exactly as relayable as generic MFA, because an attacker's lure will simply steer the victim toward whichever option the phishing page supports - which will never be the FIDO2 option, since FIDO2 cannot be phished through a proxy at all. A mixed strength gives the attacker the choice.

A Conditional Access authentication strength requirement is a server-side control, but it is only as good as the client-side provisioning behind it. The registry state below (read-only via Get-ItemProperty, never written by this audit) tells you whether a device has actually finished Windows Hello for Business provisioning - the most common reason an otherwise-correct phishing-resistant policy still generates lockout tickets.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\{GUID}\
Value name (type)Healthy valueIf wrong
DeviceEnrollmentType (REG_DWORD)0x6 (MDM-enrolled)Missing/other = device not enrolled; WHfB provisioning can't be trusted to have run under Intune policy
NgcSet under SOFTWARE\Microsoft\Ngc\{DeviceKeyId} (key presence)Key present with a valid containerAbsent = WHfB container was never provisioned on this device - user can only fall back to a relayable method
UsePassportForWork under SOFTWARE\Policies\Microsoft\PassportForWork (REG_DWORD)10/absent = WHfB policy not applied; device will keep offering password/OTP sign-in

This registry state matters for the audit because it explains a failure mode you will see in the field: a Conditional Access policy correctly requires the Phishing-resistant MFA strength, but a subset of users still cannot sign in, because their device never finished WHfB provisioning and they have no FIDO2 key. That is not a Conditional Access bug - it is a rollout gap that the policy is correctly enforcing. Fix the provisioning, not the policy.

The fix: requiring the built-in Phishing-resistant MFA strength where it matters most

You do not need to require phishing-resistant authentication for every sign-in on day one. Start with the populations where a stolen token does the most damage: administrators, anyone with standing access to finance or payroll systems, and anyone who can approve a payment or a wire. Widen the scope as WHfB and FIDO2 rollout completes.

Step 1 - Sign in to the Entra admin center and go to Protection › Conditional Access › Policies.

Step 2 - Select an existing policy that currently uses Require multifactor authentication for a sensitive population (or create a new one scoped to Global Administrators, Privileged Role Administrators, and other Tier-0 roles).

Step 3 - Under Grant, select Grant access, then change the control from Require multifactor authentication to Require authentication strength.

Step 4 - Choose the built-in Phishing-resistant MFA strength from the dropdown. Do not build a custom strength that also allows password+SMS "just in case" - that reintroduces the exact gap you are closing.

Step 5 - Set the policy to Report-only first and review the sign-in logs for a week. Anyone who would have been blocked has not finished WHfB or FIDO2 registration - fix their registration before you flip the policy to On.

Step 6 - Turn the policy On once the report-only period shows zero would-be blocks for the target population.

Protection Conditional Access Require authentication strength

Doing this policy-by-policy by hand does not scale past a handful of exceptions, and it tells you nothing about the other twenty policies you have not looked at yet. The companion script below runs the same classification logic across every enabled Conditional Access policy in the tenant in one pass.

PowerShell 7 — running the audit script
# Interactive sign-in, no app registration required
.\Get-PhishingResistantCAGapReport.ps1 -UseDeviceCode

# Unattended, app-only auth for a scheduled task
.\Get-PhishingResistantCAGapReport.ps1 -TenantId "{aaaaaaaa-0b0b-1c1c-2d2d-333333333333}" `
    -ClientId "{bbbbbbbb-1c1c-2d2d-3e3e-444444444444}" `
    -CertificateThumbprint "AAAABBBBCCCCDDDDEEEEFFFF00001111AAAABBBB" `
    -ExportCsv -CsvPath "C:\Reports\ca-authstrength-gap.csv"
Tip: Run the script with -UseDeviceCode the first time on your own workstation before wiring up an app registration. It only needs the Policy.Read.All scope and makes no changes, so it is safe to run against production immediately.

Proof it worked: reading the audit script's output

The script classifies every enabled grant-control policy into one of four buckets and prints a summary. Here is an illustrative run against a small test tenant (fictional policy names and IDs, reconstructed to show the shape of real output - never run a broad audit like this against production and paste the raw result into a public post):

PowerShell 7 — illustrative output
=== Phishing-Resistant Authentication Strength Audit ===
Policies evaluated (enabled): 7

-- Enforcing phishing-resistant authentication strength --
  [OK] CA012: Require phishing-resistant MFA for Global Administrators  ({aaaaaaaa-0b0b-1c1c-2d2d-333333333333})  Target: 4 targeted user/group/role entries

-- Gaps: relying on generic MFA or a non-phishing-resistant strength --
  [GenericMfaOnly] CA001: Require MFA for all users  ({bbbbbbbb-1c1c-2d2d-3e3e-444444444444})  Target: All users
        builtInControls = mfa, no authenticationStrength set. Any registered MFA method satisfies this, including SMS, voice, and push - all relayable by an AiTM phishing proxy.
  [MixedStrength] CA007: Require strong auth for Finance app  ({cccccccc-2d2d-3e3e-4f4f-555555555555})  Target: 1 targeted user/group/role entry
        Authentication strength 'Finance Custom Strength' also allows non-phishing-resistant combos: password,sms

Summary: 1 phishing-resistant, 2 flagged out of 7 grant-enabled policies.

What good looks like: every policy that targets a sensitive population, and ideally the "all users, all apps" baseline policy too, shows up under the [OK] section with an authentication strength whose allowed combinations are all phishing-resistant. What needs fixing: anything under GenericMfaOnly or MixedStrength - those are the policies an AiTM kit can walk straight through today, regardless of how convincing the AI-generated lure that got the user there was.

The script exits with code 1 when it finds at least one flagged policy, so it slots directly into a scheduled task or pipeline step that should fail loudly rather than silently pass. Exit code 0 means every grant-enabled policy in scope requires phishing-resistant authentication. Exit code 2 means the script could not authenticate or could not read policies at all - treat that as "could not verify," never as "clean."

Note: This audit only checks the authentication strength requirement itself. It does not check whether the target population has actually finished registering WHfB or a FIDO2 key - a policy can correctly require phishing-resistant authentication while still locking out users who have not provisioned a phishing-resistant method yet. Pair this script with a WHfB/FIDO2 registration coverage check before widening enforcement.
PowerShell Script — Phishing-Resistant CA Gap Report

Download Get-PhishingResistantCAGapReport.ps1 from Imran76Awan/Daily-Tasks on GitHub — no sign-in required. It is read-only (report-only, Graph GET calls only) — validate in your own environment before relying on it.

Get-PhishingResistantCAGapReport.ps1
Reads every Conditional Access policy via Microsoft Graph and flags which ones do not enforce a phishing-resistant authentication strength.

References

Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

AI
ChatGPT Is Now Inside Microsoft Teams — What Every IT Admin…
OpenAI has shipped admin-managed Teams sync for ChatGPT Enterprise. One Entra admin…
Windows Hello for Business
Force Phishing-Resistant Sign-In: Requiring WHfB With…
Enabling WHfB makes it available - it does not make it mandatory. A Conditional Access…
Entra ID
Your Conditional Access "Compliant Device" Check Is Trusting a…
Require device to be marked as compliant reads a stored flag, not a live device check -…