Back to Checks
m365

At least one Conditional Access Identity Protection sign-in risk policy protects against high and medium risk sign-ins

entra_identity_protection_sign_in_risk_enabled
Service: entraSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesse5
Resource Type:NotDefined

Microsoft Entra Conditional Access has a sign-in risk-based Identity Protection policy that targets All users and All cloud apps, evaluates Medium and High sign-in risk, requires MFA, sets sign-in frequency: every time, and is actively enforced not report-only.

Risk

Without this policy, risky authentications using stolen or replayed credentials may proceed without step-up verification, enabling account takeover. Attackers can establish persistent sessions, exfiltrate data, change configurations, and move laterally-eroding confidentiality and integrity and potentially impacting availability through privilege abuse.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler m365 --checks entra_identity_protection_sign_in_risk_enabled

Recommendation

Adopt a risk-based Conditional Access policy for sign-in risk that applies broadly and enforces MFA with every-time reauthentication for Medium and High risk. Align with Zero Trust and least privilege: ensure MFA enrollment, exclude emergency accounts, validate in report-only, then enforce and regularly review risky sign-in reports.

Remediation

CLI

New-MgIdentityConditionalAccessPolicy -BodyParameter @{displayName='<example_resource_name>';state='enabled';conditions=@{users=@{includeUsers=@('All')};applications=@{includeApplications=@('All')};signInRiskLevels=@('medium','high')};grantControls=@{operator='OR';builtInControls=@('mfa')};sessionControls=@{signInFrequency=@{isEnabled=$true;frequencyInterval='everyTime'}}}

Terraform

resource "azuread_conditional_access_policy" "<example_resource_name>" {
  display_name = "<example_resource_name>"
  state        = "enabled" # Critical: enforce policy

  conditions {
    users {
      include_users = ["All"] # Critical: apply to all users
    }
    applications {
      include_applications = ["All"] # Critical: apply to all apps
    }
    sign_in_risk_levels = ["medium", "high"] # Critical: protect Medium and High sign-in risks
    client_app_types    = ["all"]
  }

  grant_controls {
    operator          = "OR"
    built_in_controls = ["mfa"] # Critical: require MFA
  }

  session_controls {
    sign_in_frequency_interval = "everyTime" # Critical: require reauth every time
  }
}

Other

1Sign in to Microsoft Entra admin center (entra.microsoft.com)
2Go to Entra ID > Protection > Conditional Access > Policies > New policy
3Users: select All users
4Target resources: select All resources (All cloud apps)
5Conditions > Sign-in risk: set to Yes, select Medium and High
6Grant > Grant access: select Require multifactor authentication
7Session > Sign-in frequency: set to Every time
8Enable policy: On
9Create the policy

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 (
    ConditionalAccessGrantControl,
    ConditionalAccessPolicyState,
    RiskLevel,
    SignInFrequencyInterval,
)


class entra_identity_protection_sign_in_risk_enabled(Check):
    """Check if at least one Conditional Access policy is an Identity Protection sign-in risk policy.

    This check ensures that at least one Conditional Access policy is an Identity Protection sign-in risk policy.
    """

    def execute(self) -> list[CheckReportM365]:
        """Execute the check to ensure that at least one Conditional Access policy is an Identity Protection sign-in risk policy.

        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 is a sign-in risk based Identity Protection Policy."

        for policy in entra_client.conditional_access_policies.values():
            if policy.state == ConditionalAccessPolicyState.DISABLED:
                continue

            if "All" not in policy.conditions.user_conditions.included_users:
                continue

            if (
                "All"
                not in policy.conditions.application_conditions.included_applications
            ):
                continue

            if (
                ConditionalAccessGrantControl.MFA
                not in policy.grant_controls.built_in_controls
            ):
                continue

            if (
                SignInFrequencyInterval.EVERY_TIME
                != policy.session_controls.sign_in_frequency.interval
            ):
                continue

            report = CheckReportM365(
                metadata=self.metadata(),
                resource=policy,
                resource_name=policy.display_name,
                resource_id=policy.id,
            )
            if (
                RiskLevel.HIGH not in policy.conditions.sign_in_risk_levels
                or RiskLevel.MEDIUM not in policy.conditions.sign_in_risk_levels
            ):
                report.status = "FAIL"
                report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a sign-in risk based Identity Protection Policy but does not protect against high and medium sign-in risk attempts."
            elif policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
                report.status = "FAIL"
                report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a sign-in risk based Identity Protection Policy and reports high and medium risk potential sign-in attempts, but does not protect against them."
            else:
                report.status = "PASS"
                report.status_extended = f"Conditional Access Policy '{policy.display_name}' is a sign-in risk based Identity Protection Policy and does protect against high and medium risk potential sign-in attempts."
                break

        findings.append(report)

        return findings