I’ve gathered the Conditional Access tributes from nearly every district, and today, we’re collecting the final ones as we approach the Capitol.
Conditional Access is one of the sharpest tools in our Identity & Access Management arsenal. We’ve already covered policies for workloads, privileged access and baseline essentials. Today, we’re diving into the policies that didn’t quite fit into the other posts’ themes. The lineup includes device-based policies, insider risk, user and sign-in risk.
As powerful as these policies are, they need to be implemented thoughtfully. Some might require deeper evaluation, additional licensing, or simply might not be a fit for your specific environment. As always, don’t just take my word for it—roll them out gradually to avoid potential issues. I’ll be sharing insights into each of these policies, so let’s get started.
Table of content:
Let's talk risk - Numbers for the C-suite
The European Union Agency for Cybersecurity (ENISA) has identified seven major threats in the current cybersecurity landscape for 2024:
Ransomware
Malware
Social Engineering
Threats against data
Threats against availability: Denial of Service
Information manipulation and interference
Supply chain attacks
On top of that, Trend Micro's midyear threat report highlights how the threat landscape is evolving rapidly due to the growing incorporation of AI into cyberattacks.
Generative AI has been supercharging identity-focused attacks, as seen in reports from ENISA and CrowdStrike, which show a 20% surge in identity-driven attacks, particularly in more sophisticated social engineering campaigns. And this isn’t just a warning—it’s happening right now.
CrowdStrike also reported a staggering 110% year-over-year increase in cloud-conscious attacks in 2023. Combine that with the surge in identity-targeted attacks, and it’s clear that securing cloud-based identity systems like Entra ID is more critical than ever.
While ransomware and DDoS attacks top the charts for most reported cybercrimes, we may not be able to mitigate DDoS through Conditional Access. However, we can definitely address ransomware, especially considering identity compromise is one of the favored tactics in these attacks.
Cyber Attack Motivations
These identity-based attacks go beyond financial ransomware campaigns. Especially here in the EU, where geopolitical tensions are currently at their peak, motivations behind these attacks have diversified. According to ENISA’s findings, attackers are driven by:
Espionage
Financial gain
Ideological reasons
Destruction
Financial gain and ideology tops the list as primary motivators. With cybercrime expected to cost the global economy $10.5 trillion annually by 2025, securing corporate identities is no longer just an option—it’s a critical requirement.
Conditional Access: A Single Cog in a Bigger Machine
While Conditional Access Policies (CAP) play a crucial role, they are only one piece of the broader cybersecurity puzzle. Even if you implement every CAP I’ve recommended in this series, there’s still more to do to secure your environment fully.
Now, with all the gloom and doom out of the way, let’s dive into the CAPs and explore their rationale.
Conditional Access: The signals
The policies in this post leverage various conditional access signals, focusing on risk-based indicators.
To better understand these signals, let's quickly walk through each one, how to set it up, and what it’s used for.
Microsoft Entra Identity Protection: Risk signals
Entra Identity Protection risks comes in two different flavors
Sign-In risk: These risks relate to authentication attempts, flagged by signals like Anonymous IP addresses or detections from Entra Threat Intelligence (e.g., Password Spray Attacks, Unfamiliar Sign-In Properties).
User risk: These risks are tied to user-specific threats, such as Leaked credentials or sophisticated threats like Adversary in the Middle.
Sign-in and user risks are automatically collected within Entra Identity Protection, without extra configuration. However, for tenants using Entra Free or Entra P1, collected risk signals are limited, with no option for remediation in Entra or PowerShell.
Microsoft Entra P2 licensing is required to manage risks manually, automate remediation via Conditional Access, or programmatically with PowerShell. Entra P2 also expands the available risk detections, which you can explore in Microsoft’s full list of Premium Risk Detections.
Risk levels are categorized by Microsoft’s machine-learning-driven confidence in the threat:
None
Low
Medium
High
The level reflects Microsoft’s confidence in the accuracy of the detection—not the severity of the event itself. A high-risk level indicates high confidence, medium indicates moderate confidence, and low reflects minimal confidence. If no risk is detected, the level is marked as "None."
You can review risks in your organization through either the Microsoft Entra Portal or PowerShell:
Microsoft Entra Portal
Sign in to the Microsoft Entra portal and navigate to the Protection blade, then select Risky Activities. The options under "Report" allow you to filter risks based on your focus.
PowerShell Script for Risk Data Collection
Run this PowerShell script to gather risk events by identity:
Powershell script collecting all risk events by identity
# Install and import Microsoft Graph Beta Module
Write-Output "Installing and importing Microsoft Graph Beta Module..."
Install-Module Microsoft.Graph.Beta -Force -AllowClobber
Import-Module Microsoft.Graph.Beta
# Connect to Microsoft Graph Beta with the required scopes
Write-Output "Connecting to Microsoft Graph Beta with necessary permissions..."
Connect-MgGraph -Scope "IdentityRiskEvent.Read.All,IdentityRiskyServicePrincipal.Read.All,IdentityRiskyUser.Read.All,User.Read.All"
# Table 1: Collect all risky sign-ins using Get-MgBetaRiskDetection
Write-Output "Collecting all risky sign-ins from Microsoft Graph Beta API..."
$riskDetectionSummary = @()
$allRiskDetections = Get-MgBetaRiskDetection
foreach ($riskDetection in $allRiskDetections) {
# Extract nested fields from AdditionalInfo
$riskReasons = ""
$userAgent = ""
if ($riskDetection.AdditionalInfo) {
foreach ($info in $riskDetection.AdditionalInfo) {
if ($info.Key -eq "riskReasons") {
$riskReasons = ($info.Value -join ", ")
}
elseif ($info.Key -eq "userAgent") {
$userAgent = $info.Value
}
}
}
# Create a summary object for each risky sign-in detection
$riskSummaryObject = [PSCustomObject]@{
Activity = $riskDetection.Activity
ActivityDateTime = $riskDetection.ActivityDateTime
DisplayName = $riskDetection.UserDisplayName
PrincipalName = $riskDetection.UserPrincipalName
RiskLevel = $riskDetection.RiskLevel
RiskState = $riskDetection.RiskState
RiskType = $riskDetection.RiskType
DetectionTime = $riskDetection.DetectedDateTime
IPAddress = $riskDetection.IPAddress
RiskReasons = $riskReasons
UserAgent = $userAgent
MitreTechnique = $riskDetection.MitreTechniqueId
Source = $riskDetection.Source
Status = if ($riskDetection.RiskState -eq "atRisk") { "Currently Risky" } else { "Previously Risky" }
}
$riskDetectionSummary += $riskSummaryObject
}
# Table 2: Collect all risky users using Get-MgBetaRiskyUser
Write-Output "Collecting all risky users and associated risk events..."
$riskyUsersSummary = @()
$riskyUsers = Get-MgBetaRiskyUser
# Retrieve all risk detections
$allUserRiskDetections = Get-MgBetaRiskDetection
foreach ($user in $riskyUsers) {
# Retrieve DisplayName if not provided by Get-MgBetaRiskyUser
$displayName = $user.DisplayName
if (-not $displayName) {
try {
$userDetails = Get-MgBetaUser -UserId $user.UserPrincipalName -ErrorAction SilentlyContinue
if ($userDetails) {
$displayName = $userDetails.DisplayName
}
} catch {
Write-Output "Warning: Could not retrieve details for user $($user.UserPrincipalName)"
}
}
$userRiskEvents = $allUserRiskDetections | Where-Object { $_.UserPrincipalName -eq $user.UserPrincipalName }
$latestDetectionTime = ($userRiskEvents | Sort-Object -Property DetectedDateTime -Descending | Select-Object -First 1).DetectedDateTime
$userSummaryObject = [PSCustomObject]@{
DisplayName = $displayName
PrincipalName = $user.UserPrincipalName
RiskLevel = $user.RiskLevel
RiskState = $user.RiskState
RiskDetail = $user.RiskDetail
LastDetectedRisk = $latestDetectionTime
Status = if ($user.RiskState -eq "atRisk") { "Currently Risky" } else { "Previously Risky" }
}
$riskyUsersSummary += $userSummaryObject
}
# Table 3: Collect all risky service principals using Get-MgBetaRiskyServicePrincipal
Write-Output "Collecting all risky service principals and associated risk events..."
$riskyServicePrincipalsSummary = @()
$riskyServicePrincipals = Get-MgBetaRiskyServicePrincipal
# Retrieve risk detections for all service principals
$allServicePrincipalRiskDetections = Get-MgBetaRiskDetection
foreach ($servicePrincipal in $riskyServicePrincipals) {
$servicePrincipalRiskEvents = $allServicePrincipalRiskDetections | Where-Object { $_.ServicePrincipalId -eq $servicePrincipal.Id }
$latestDetectionTime = ($servicePrincipalRiskEvents | Sort-Object -Property DetectedDateTime -Descending | Select-Object -First 1).DetectedDateTime
$servicePrincipalSummaryObject = [PSCustomObject]@{
DisplayName = $servicePrincipal.DisplayName
PrincipalId = $servicePrincipal.Id
AppId = $servicePrincipal.AppId
RiskLevel = $servicePrincipal.RiskLevel
RiskState = $servicePrincipal.RiskState
LastDetectedRisk = $latestDetectionTime
Status = if ($servicePrincipal.RiskState -eq "atRisk") { "Currently Risky" } else { "Previously Risky" }
}
$riskyServicePrincipalsSummary += $servicePrincipalSummaryObject
}
# Display summarized data in separate tables
Write-Output "`nDisplaying Table 1: Risky Sign-Ins Summary"
$riskDetectionSummary | Format-Table -Property Activity, ActivityDateTime, DisplayName, PrincipalName, RiskLevel, RiskState, RiskType, DetectionTime, IPAddress, RiskReasons, UserAgent, MitreTechnique, Source, Status -AutoSize
Write-Output "`nDisplaying Table 2: Risky Users Summary"
$riskyUsersSummary | Format-Table -Property DisplayName, PrincipalName, RiskLevel, RiskState, RiskDetail, LastDetectedRisk, Status -AutoSize
Write-Output "`nDisplaying Table 3: Risky Service Principals Summary"
$riskyServicePrincipalsSummary | Format-Table -Property DisplayName, PrincipalId, AppId, RiskLevel, RiskState, LastDetectedRisk, Status -AutoSize
Microsoft Purview: Insider Risk Signals
Insider risk is a significant threat in today’s security landscape.
To manage these risks effectively, we’ll utilize Microsoft’s solution for identifying and protecting against insider threats. The signals used here are based on the Insider Risk Management solution Adaptive Protection within Microsoft Purview, a flexible, customizable tool for insider risk management.
According to the Cybersecurity & Infrastructure Security Agency (CISA), insider risks are identified as falling into these categories:
Unintentional Threats: These include negligent actions that expose the organization to risks due to carelessness, such as sending emails to incorrect recipients or clicking on phishing links.
Intentional Threats: Also known as "Malicious Insider" threats, these are deliberate actions meant to harm the organization, often due to perceived unfair treatment.
Collusive Threats: External actors may recruit insiders, often through incentives or blackmail, to compromise organizational security.
Third-Party Threats: This risk arises from external users like contractors, partners, or vendors who have access to corporate data.
Adaptive Protection in Microsoft Purview relies on machine-learning to assess and respond to these insider risks:
Context-Aware Detection: AI-driven analysis identifies critical risks by evaluating both content and user activities.
Dynamic Controls: Allows heightened security for high-risk users while ensuring low-risk users maintain productivity.
Automated Mitigation: Minimizes potential data security incidents and reduces admin workload.
Insider risk levels in Adaptive Protection have the following default configuration:
Note that using Adaptive Protection requires either a Microsoft 365 E5 or Microsoft 365 E5 compliance add-on license.
Conditional Access: Risky Business
As mentioned, we'll be going through a mishmash of policies, and therefore I'll be switching the format up somewhat from my earlier posts, and will provide an explanation directly at the policies below.
Short reminder of the naming scheme.
<CANumber>-<GrantControl>-<PolicyType>-<Persona>-<App>-<Platform>-<OptionalDescription>
CAP 35:
CA003-Block-DataProtection-Global-AllApps-AnyPlatform-Block Elevated insider risk v1.0
This policy blocks all access for users flagged with an elevated insider risk profile. As we went over in the previous segment, elevated risks often signal potentially severe internal threats where a user could exfiltrate or manipulate sensitive data, whether intentional or not. This policy shuts down access preemptively to protect against malicious actions before they escalate.
NOTE: Be sure to exclude your breakglass, service accounts and B2B/external personas, as they are not supported for this risk type. - Requires at least Microsoft 365 E5 compliance add-on license.
CAP 36:
CA004-Block-DataProtection-Global-O365-AnyPlatform-Block business critical apps for Moderate insider risk v1.0
This policy prevents moderate-risk users from accessing critical business applications, which could hold properitary information, or otherwise sensitive data. By blocking these users, this policy minimizes chances of accidental or calculated misuse, especially for applications essential to your organization’s core functions.
NOTE: Be sure to reconfigure the policy for your organizations critical business applications, this is an example using O365, but should be updated based on your environment. - Requires at least Microsoft 365 E5 compliance add-on license.
CAP 37:
CA005-Block-AttackSurfaceReduction-Global-AllApps-AnyPlatform-Block Device code flow v1.0
Device code flow authentication, which allows authentication from a different device, is disabled via this policy, this is due to this authentication type being vulnerable to different attacks such as impersonation, especially in phishing.
NOTE: You should exclude applications, devices or identities as your environment needs it as it does have a legitimate use case, specifically for devices with limited interactivability.
CAP 38:
CA400-Block-AttackSurfaceReduction-Finance-AllApps-AnyPlatform-Block Authentication Transfer for Finance v1.0
Blocks authentication transfers, to shield highly sensitive data from unauthorized access. This policy restricts potential lateral movement by attackers, which could otherwise lead to escalated privilege and substantial damage.
NOTE: This example is created for the specific persona being the finance department, this will need to be modified depending on your environment, it might be a group, specific users or multiple personas. If you choose to change the persona to global, make sure to update the CA number as well.
CAP 39:
CA505-MFA&PWDreset-IdentityProtection-Global-AllApps-AnyPlatform-Require Password reset and MFA for High user risk v1.0
Requires users flagged as high-risk to complete both a password reset and MFA, which completes the remediation steps for the user risk, restoring user access, while mitigating the high-confidence user compromise.
NOTE: Make sure to exclude breakglass, Service Accounts and B2B/external personas, as they are not supported for user risk policies. - Requires at least Microsoft Entra P2 license.
CAP 40:
CA506-MFA-IdentityProtection-Global-AllApps-AnyPlatform-Require MFA for Medium & High sign-in risk v1.0
Mandates MFA for sign-ins tagged with medium or high risk, catching potential misuse without restricting access. This extra authentication prompt guards against typical attacks like password spraying and brute force attacks.
NOTE: Sign-in risks are supported for B2B/external personas, but breakglass and Service Accounts should be excluded. - Requires at least Microsoft Entra P2 license.
CAP 41:
CA507-MFA-IdentityProtection-Global-AllApps-AnyPlatform-Require MFA for Low & Medium user risk v1.0
Enforcing MFA on users with low and medium risk, allows self-remediation for lower-confidence flagging, without inconveniencing the user too much. Even at lower levels, MFA serves as a critical stopgap to prevent unauthorized access.
NOTE: Make sure to exclude breakglass, Service Accounts and B2B/external personas, as they are not supported for user risk policies. - Requires at least Microsoft Entra P2 license.
CAP 42:
CA508-TOU-ComplianceProtection-Global-AllApps-AnyPlatform-Require TOU acceptance for Minor insider risk v1.0
This policy is based on the presumption that the minor risk stems from unintentional actions and prompts the minor insider risk user to accept the internal Terms of Use (TOU) before granting access. This gently reminds the user of the organization’s compliance standards and expected behavior.
This policy utilizes awareness as a deterrent, subtly reinforcing security culture and ensuring at-risk individuals are conscious of their responsibilities, and actions, which in turn can dissuade negligent or unintentional risky behaviors.
NOTE: Be sure to exclude your breakglass, service accounts and B2B/external personas, as they are not supported for this risk type. - Requires at least Microsoft 365 E5 compliance add-on license.
Conclusion: Playing Defense Like a Pro – The Final Countdown Begins!
Today’s policies are all about playing defense where it matters most, adding that extra layer of vigilance for risky users, devices, and insider threats.
With these policies targeting risky sign-ins, suspicious user behavior, and device-based vulnerabilities, we’ve established a defense perimeter that’s both reactive and proactive, preventing incidents while enabling active self-remediation for our users.
Conditional Access may only be one part of our security toolkit and strategy, but it’s a critical one. These configurations make our organizations less vulnerable to common attack vectors and insider risks while keeping access smooth for our trusted users. It’s a win-win: productivity stays high, and risk remains low—a benefit for both us as IT Pros and our decision-makers alike.
With all that out of the way, I'll once again leave you with another bad joke, to brighten your day:
Why did the hacker get kicked out of the security party?
Because he couldn’t stop phishing for compliments! 😎
This post is the penultimate post in the series so, what’s next? In our series finale, we’ll wrap it all up with the final policies, focused on 1st party application policies, that will bring your Conditional Access strategy full circle.
Join me next time to put the finishing touches on your security setup—see you in the last round!
And as always, if you found this helpful, give it a like, leave a comment, and don’t forget to bookmark the blog to stay updated!
Comments