Back to Checks
At least one Conditional Access policy requires phishing-resistant MFA strength for administrator roles
entra_admin_users_phishing_resistant_mfa_enabled
Service: entraSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesse3
Resource Type:NotDefined
Microsoft Entra Conditional Access for administrator roles requires phishing-resistant MFA authentication strength on All applications. Disabled policies are ignored; report-only policies aren't considered. Policies with custom strengths require review to confirm they are truly phishing-resistant.
Risk
Without phishing-resistant MFA on admin accounts, attackers can:
- Bypass OTP/push via AiTM phishing
- Abuse MFA fatigue to gain sessions
- Perform tenant takeover, alter policies, and exfiltrate data
This harms confidentiality, configuration integrity, and service availability.
Run this check with Prowler
Run in Prowler CloudRun
prowler m365 --checks entra_admin_users_phishing_resistant_mfa_enabledRecommendation
Require Phishing-resistant MFA via Conditional Access for all privileged roles and All resources. Favor FIDO2, Windows Hello for Business, or certificate-based auth. Apply least privilege, use PIM for step-up on role activation, test in report-only, and keep a monitored break-glass account.
Remediation
Other
1Sign in to Microsoft Entra admin center (https://entra.microsoft.com)
2Go to Entra ID > Conditional Access > Policies > New policy
3Users > Include > Directory roles > select Global Administrator (or the admin roles you require)
4Target resources > Resources (cloud apps) > Include > All cloud apps; ensure Exclude is empty
5Grant > Grant access > Require authentication strength > select Phishing-resistant MFA > Select
6Enable policy: On
7Click Create
Check Code
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.entra.entra_client import entra_client
from prowler.providers.m365.services.entra.entra_service import (
AdminRoles,
ConditionalAccessPolicyState,
)
class entra_admin_users_phishing_resistant_mfa_enabled(Check):
"""Check if Conditional Access policies require Phishing-resistant MFA strength for admin users."""
def execute(self) -> list[CheckReportM365]:
"""Execute the check to ensure that Conditional Access policies require Phishing-resistant MFA strength for admin users.
Returns:
list[CheckReportM365]: A list containing the results of the check.
"""
findings = []
report = CheckReportM365(
metadata=self.metadata(),
resource={},
resource_name="Conditional Access Policies",
resource_id="conditionalAccessPolicies",
)
report.status = "FAIL"
report.status_extended = "No Conditional Access Policy requires Phishing-resistant MFA strength for admin users."
for policy in entra_client.conditional_access_policies.values():
if policy.state == ConditionalAccessPolicyState.DISABLED:
continue
if not (
{role.value for role in AdminRoles}.issuperset(
policy.conditions.user_conditions.included_roles
)
):
continue
if (
"All"
not in policy.conditions.application_conditions.included_applications
or policy.conditions.application_conditions.excluded_applications != []
):
continue
if (
policy.grant_controls.authentication_strength is not None
and policy.grant_controls.authentication_strength
!= "Multifactor authentication"
and policy.grant_controls.authentication_strength != "Passwordless MFA"
and policy.grant_controls.authentication_strength
!= "Phishing-resistant MFA"
):
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.display_name,
resource_id=policy.id,
)
report.status = "MANUAL"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' has a custom authentication strength, review it is Phishing-resistant MFA."
continue
if (
policy.grant_controls.authentication_strength is not None
and policy.grant_controls.authentication_strength
== "Phishing-resistant MFA"
):
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.display_name,
resource_id=policy.id,
)
if policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
report.status = "FAIL"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' reports Phishing-resistant MFA strength for admin users but does not require it."
else:
report.status = "PASS"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' requires Phishing-resistant MFA strength for admin users."
break
findings.append(report)
return findingsReferences
- https://blog.admindroid.com/use-phishing-resistant-mfa-to-implement-stronger-mfa-authentication/
- https://learn.microsoft.com/en-us/entra/identity/conditional-access/policy-admin-phish-resistant-mfa#create-a-conditional-access-policy
- https://docs.azure.cn/en-us/entra/identity/conditional-access/policy-guests-mfa-strength
- https://learn.microsoft.com/en-us/entra/identity/conditional-access/policy-admin-phish-resistant-mfa