Audit User Marked As Compromised By Admin Or App
Query
AuditLogs
| where OperationName == "ConfirmAccountCompromised"
| extend IntiatedBy = parse_json(tostring(InitiatedBy.user)).userPrincipalName //Person who did the confirm Compromise. It may be an app
| extend ServicePrincipalId = tostring(parse_json(tostring(InitiatedBy.app)).appId)
| extend UserId = tostring(TargetResources[0].id) //Extract Target User Id
| join kind=leftouter (SigninLogs|where UserPrincipalName contains "@" |summarize by UserPrincipalName,UserId) on UserId //If UPN is missing use sign-in logs to gather it
| join kind=leftouter (AADServicePrincipalSignInLogs| summarize by ServicePrincipalId, ServicePrincipalName) on ServicePrincipalId //If an SP marked compromised use this to gather app display name
| join kind=leftouter (AADManagedIdentitySignInLogs| summarize by ServicePrincipalId, ServicePrincipalName) on ServicePrincipalId //IF MI marked compromised
| project-away UserId1, UserId, Type, AADOperationType, Level, DurationMs, ResultSignature, OperationVersion, Resource, ResourceGroupExplanation
This query is designed to analyze audit logs to identify and provide details about accounts that have been confirmed as compromised. Here's a simplified breakdown of what the query does:
-
Filter Audit Logs: It starts by filtering the
AuditLogstable to only include entries where the operation name is "ConfirmAccountCompromised". This means it focuses on events where an account has been marked as compromised. -
Extract Initiator Information: It extracts the user principal name of the entity (person or application) that confirmed the account compromise. This is stored in a new column called
InitiatedBy. -
Extract Service Principal ID: It extracts the application ID if the initiator is an application, storing it in a column named
ServicePrincipalId. -
Extract Target User ID: It extracts the ID of the user account that was marked as compromised, storing it in a column named
UserId. -
Join with Sign-in Logs: It performs a left outer join with the
SigninLogstable to find the user principal name (UPN) for the compromised account if it's missing, using theUserIdas the key for joining. -
Join with Service Principal Sign-in Logs: It performs another left outer join with the
AADServicePrincipalSignInLogstable to get the display name of the application if a service principal (SP) was marked as compromised, using theServicePrincipalIdas the key. -
Join with Managed Identity Sign-in Logs: It performs a similar join with the
AADManagedIdentitySignInLogstable to get the display name if a managed identity (MI) was marked as compromised. -
Project Away Unnecessary Columns: Finally, it removes unnecessary columns from the result to clean up the output, keeping only the relevant information.
In summary, this query identifies compromised accounts, provides details about who confirmed the compromise, and enriches the data with additional information from sign-in logs to give a clearer picture of the compromised accounts and any associated applications.
Details

Jay Kerai
Released: May 13, 2025
Tables
Keywords
Operators