Use this skill when asked to investigate Conditional Access policy changes, sign-in failures related to CA policies (error codes 53000, 50074, 530032), or suspected policy bypass/manipulation...
This skill investigates Conditional Access (CA) policy changes in correlation with sign-in failures to detect:
The key distinction is whether policy changes were authorized and necessary vs self-service bypass of security controls.
When investigating sign-in failures (error codes 53000, 50074) with CA policy correlation:
⚠️ MANDATORY STEPS - DO NOT SKIP:
Key Questions to Answer:
| Error Code | Description | Typical Cause |
|---|---|---|
| 53000 | Device not compliant | Device not enrolled in Intune or failing compliance checks |
| 50074 | Strong authentication required | MFA not satisfied |
| 50074 | User must enroll in MFA | MFA not configured for user |
| 530032 | Blocked by CA policy | Generic CA policy block |
| 65001 | User consent required | Application consent needed |
| 53003 | Access blocked by CA policy | Explicit block condition met |
| 70044 | Session expired | User needs to re-authenticate |
| Priority | Error Codes | Investigation Focus |
|---|---|---|
| HIGH | 53000, 530032, 53003 | Device compliance, CA policy blocks - check for policy manipulation |
| MEDIUM | 50074 | MFA requirements - check if MFA was bypassed |
| LOW | 65001, 70044 | Consent/session issues - usually not security-related |
| State | What It Means | Security Impact |
|---|---|---|
| enabled | Policy actively enforcing | Blocks non-compliant access (intended behavior) |
| disabled | Policy not enforcing | Security control bypassed - all access allowed |
| enabledForReportingButNotEnforced | Report-only mode | Logs violations but doesn't block - defeats purpose |
| Transition | Risk Level | Interpretation |
|---|---|---|
enabled → disabled |
HIGH | Complete security bypass |
enabled → enabledForReportingButNotEnforced |
MEDIUM-HIGH | Partial bypass (monitoring only) |
disabled → enabled |
LOW | Security restored (good) |
enabledForReportingButNotEnforced → enabled |
LOW | Security strengthened (good) |
Query sign-in failures with CA context:
// Get failures with CA context
union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated between (datetime(<START>) .. datetime(<END>))
| where UserPrincipalName =~ '<UPN>'
| where ResultType != '0'
| where AppDisplayName has '<APPLICATION>' // e.g., "Visual Studio Code"
| project TimeGenerated, IPAddress, Location, ResultType, ResultDescription,
ConditionalAccessStatus, UserAgent
| order by TimeGenerated asc
What to Look For:
ResultType values: 53000, 50074, 530032, 53003ConditionalAccessStatus: "failure", "notApplied"CRITICAL: Query ±2 days from the first failure time
let failure_time = datetime(<FIRST_FAILURE_TIME>);
let start = failure_time - 2d;
let end = failure_time + 2d;
AuditLogs
| where TimeGenerated between (start .. end)
| where OperationName has_any ("Conditional Access", "policy")
| where Identity =~ '<UPN>' or tostring(InitiatedBy) has '<UPN>'
| extend InitiatorUPN = tostring(parse_json(InitiatedBy).user.userPrincipalName)
| extend InitiatorIPAddress = tostring(parse_json(InitiatedBy).user.ipAddress)
| extend TargetName = tostring(parse_json(TargetResources)[0].displayName)
| project TimeGenerated, OperationName, Result, InitiatorUPN, InitiatorIPAddress,
TargetName, CorrelationId
| order by TimeGenerated asc // CRITICAL: Chronological order
Critical Analysis Points:
For each CorrelationId from Step 2, get detailed changes:
// Get detailed property changes for a specific policy modification
AuditLogs
| where CorrelationId == "<CORRELATION_ID>"
| extend ModifiedProperties = parse_json(TargetResources)[0].modifiedProperties
| mv-expand ModifiedProperties
| extend PropertyName = tostring(ModifiedProperties.displayName)
| extend OldValue = tostring(ModifiedProperties.oldValue)
| extend NewValue = tostring(ModifiedProperties.newValue)
| project TimeGenerated, PropertyName, OldValue, NewValue
Key Properties to Extract:
"state" property in the JSONOldValue and NewValue for state transitionsenabled → disabled → enabledForReportingButNotEnforcedManual JSON Parsing:
The OldValue and NewValue fields contain JSON. Look for the "state" field:
{
"state": "enabled",
"conditions": { ... },
"grantControls": { ... }
}
Build the Timeline:
"state" from each OldValue and NewValueenabled → disabled → enabledForReportingButNotEnforcedCompare timelines and assess intent:
| Pattern | Interpretation | Risk Level |
|---|---|---|
| Failures → Policy Disabled | User bypassed security control to unblock self | HIGH - Privilege abuse |
| Failures → Policy Changed to Report-Only | User weakened security control | MEDIUM-HIGH - Partial bypass |
| Policy Disabled → Failures Continue | Cached tokens (5-15 min propagation delay) | INFO - Expected behavior |
| Policy Changed → No More Failures | Policy change resolved issue | Context-dependent - May be legitimate troubleshooting |
| Different user made change | Admin assisted with access issue | LOW - Likely legitimate (verify authorization) |
Risk Escalation Criteria:
| Criteria | Risk Level |
|---|---|
| Same user blocked AND made policy change | HIGH |
| Policy disabled within 30 minutes of first failure | HIGH |
| Multiple policies modified | HIGH |
| Change made outside business hours | MEDIUM-HIGH |
| No change request ticket/approval | MEDIUM-HIGH |
| Admin made change for blocked user (with ticket) | LOW |
Scenario: User blocked by device compliance policy, then modifies policy
| Time | Event | Details |
|---|---|---|
| 19:05 | Sign-in failure | Error 53000: device not compliant |
| 19:06 | Sign-in failure | Error 53000: device not compliant |
| 19:07 | Sign-in failure | Error 53000: device not compliant |
| 19:09 | Policy change | enabled → disabled |
| 19:09 | Policy change | disabled → enabledForReportingButNotEnforced |
| 19:12 | Sign-in failure | Error 53000 (cached token) |
| 19:14 | Sign-in success | Access granted |
✅ Policy was correctly blocking non-compliant device
🚨 User disabled security control to bypass block
⚠️ User partially reversed by enabling report-only
❌ Report-only mode is NOT a valid security posture
| Field | Value |
|---|---|
| Risk Level | MEDIUM-HIGH |
| Finding | Self-service security bypass using privileged role |
| Root Cause | User's device is non-compliant (not enrolled/failing compliance) |
| Policy Impact | Device compliance checks now ineffective for all users |
Immediate Actions:
enabled stateUser-Specific:
Process Improvements:
| Mistake | Why It's Wrong |
|---|---|
| Query only ONE policy change event | You'll miss the sequence of changes |
| Read policy changes in reverse chronological order | Confuses cause/effect relationship |
| Assume policy was already disabled | Must check starting state from OldValue |
| Skip verifying "does this make logical sense?" | Disabled policies can't block users |
| Ignore the initiator identity | Same user = suspicious, different admin = verify authorization |
| Focus only on final state | The transition sequence reveals intent |
| Best Practice | Why It Matters |
|---|---|
| Query ALL policy changes in the timeframe | Complete picture of modifications |
| Order chronologically (oldest first) | See cause/effect sequence |
| Parse the full JSON for state transitions | Extract exact policy states |
| Cross-check: blocked user → policy must be enabled | Logical consistency verification |
| Ask: "Why would user disable this policy?" | Usually to bypass a legitimate block |
| Check if initiator had authorization | Ticket, approval, documented reason |
| Action | Priority |
|---|---|
Restore policy to enabled state if unauthorized |
IMMEDIATE |
| Investigate root cause (why was user blocked?) | HIGH |
| Fix underlying issue (device compliance, MFA enrollment) | HIGH |
| Review who has permission to modify CA policies | MEDIUM |
| Implement approval workflows for policy changes | MEDIUM |
| Create alerts for future CA policy modifications | MEDIUM |
| Improvement | Benefit |
|---|---|
| Use PIM for Security Administrator role | Requires approval for elevated access |
| Implement CA policy change alerts | Real-time notification of modifications |
| Require multi-admin approval for state changes | Prevents single-person bypass |
| Document approved procedures | Clear guidance for legitimate troubleshooting |
| Regular access reviews | Ensure only necessary users have CA admin rights |
This skill requires:
mcp_sentinel-data_query_lake: Execute KQL queriesmcp_sentinel-data_search_tables: Discover table schemasTo view CA policy changes in AuditLogs, ensure:
CA Policy Investigation often follows a user-investigation:
Key Integration Points: