Audit Logs Entra ID User Created By Unexpected Actor
Query
let _EntraConnectSyncAccounts = toscalar(
_GetWatchlist("Activity-ExpectedSignificantActivity")
| where Activity == "EntraConnectSync"
| summarize make_list(ActorId)
);
let _ExpectedCrossTenantSynchronization =
_GetWatchlist("Activity-ExpectedSignificantActivity")
| where Activity == "CrossTenantSynchronization"
| project InitiatorId = tostring(ActorId), CrossSynchronizationDomain = tostring(Auxiliar)
;
AuditLogs
| where OperationName == "Add user" and Result == "success"
| extend
Initiator = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["displayName"]), tostring(InitiatedBy["user"]["userPrincipalName"])),
InitiatorId = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["servicePrincipalId"]), tostring(InitiatedBy["user"]["id"])),
IPAddress = tostring(InitiatedBy[tostring(bag_keys(InitiatedBy)[0])]["ipAddress"])
| where not(InitiatorId in (_EntraConnectSyncAccounts))
| mv-apply ModifiedProperty = TargetResources[0]["modifiedProperties"] on (
extend NewValue = todynamic(tostring(ModifiedProperty["newValue"]))
| summarize TargetUserProperties = make_bag(pack(tostring(ModifiedProperty["displayName"]), iff(array_length(NewValue) == 1, tostring(NewValue[0]), NewValue)))
)
| extend
TargetUserType = tostring(TargetUserProperties["UserType"]),
TargetUserPrincipalName = tostring(TargetResources[0]["userPrincipalName"]),
TargetId = tostring(TargetResources[0]["id"])
| where not(TargetUserType == "Guest")
| extend CrossSynchronizationDomain = extract(@"\_([^\_]+)\#EXT\#\@[^\@]+\.onmicrosoft\.com$", 1, TargetUserPrincipalName)
| join kind=leftanti _ExpectedCrossTenantSynchronization on InitiatorId, CrossSynchronizationDomain
| project
TimeGenerated,
LoggedByService,
Category,
AADOperationType,
Initiator,
IPAddress,
OperationName,
Result,
ResultDescription,
TargetUserType,
TargetUserPrincipalName,
CrossSynchronizationDomain,
TargetId,
TargetUserProperties,
AdditionalDetails,
InitiatorId,
InitiatedBy,
TargetResources,
CorrelationIdExplanation
This KQL query is designed to analyze audit logs for user addition activities in a system, specifically focusing on identifying potentially unauthorized or unexpected user additions. Here's a simplified breakdown of what the query does:
-
Define Expected Accounts and Activities:
- It first retrieves a list of expected accounts involved in "EntraConnectSync" activities from a watchlist named "Activity-ExpectedSignificantActivity".
- It also retrieves expected cross-tenant synchronization activities from the same watchlist, mapping the initiator IDs and associated domains.
-
Filter Audit Logs:
- The query then filters audit logs to find successful "Add user" operations.
- It extracts details about the initiator of these operations, including their ID and IP address.
-
Exclude Expected Accounts:
- It excludes operations initiated by accounts involved in "EntraConnectSync" activities, as these are expected and not of interest for this analysis.
-
Analyze Modified Properties:
- For each user addition, it examines the modified properties to create a summary of the target user's properties.
-
Exclude Guest Users:
- It filters out any operations that added guest users, focusing only on non-guest user additions.
-
Identify Cross-Tenant Synchronization:
- It attempts to extract the domain from the target user's principal name to identify cross-tenant synchronization activities.
- It then excludes any operations that match expected cross-tenant synchronization activities.
-
Project Relevant Information:
- Finally, it projects a set of relevant fields, such as the time of the operation, the service that logged it, the initiator details, the operation result, and details about the target user.
In summary, this query is used to identify and list potentially unauthorized user additions by filtering out expected and authorized activities, focusing on unexpected or suspicious user additions in the audit logs.
Details

Jose Sebastián Canós
Released: March 7, 2025
Tables
AuditLogs
Keywords
AuditLogs
Operators
lettoscalar_GetWatchlistwheresummarizemake_listprojecttostringAuditLogsandextendiifisnotemptybag_keysnotinmv-applyontodynamicmake_bagpackarray_lengthiffjoinkindleftantiextract