Risky External Privileged Users With Enrichment Of Known Attack Paths And Tiering
Query
// Early draft: List of Directory Roles including known attack paths (defined by Emilien Socchi repository: https://github.com/emiliensocchi/azure-tiering/blob/main/Entra%20roles/tiered-entra-roles.json), classification by EntraOps, categories and rich details by Graph API and their role members with flags for Guest, Risky User and count of role members from IdentityInfo.
let SensitiveEntraDirectoryRoles = externaldata(RoleName: string, RoleId: string, Categories: string, RichDescription: string, isPrivileged: bool, Classification: dynamic, RolePermissions:dynamic)["https://raw.githubusercontent.com/Cloud-Architekt/AzurePrivilegedIAM/main/Classification/Classification_EntraIdDirectoryRoles.json"] with(format='multijson')
| where Classification.EAMTierLevelName != "Unclassified"
| mv-expand RolePermissions
| extend Categories = split(Categories,',')
| summarize EntraOpsCategory = make_set(RolePermissions.Category), Categories = make_set(Categories) by RoleName, RoleId, isPrivileged, EntraOpsClassification = tostring(Classification.EAMTierLevelName), RichDescription;
let KnownAttackPaths = externaldata(id: string, pathType: string, knownShortestPath: string, example: string)["https://raw.githubusercontent.com/emiliensocchi/azure-tiering/main/Entra%20roles/tiered-entra-roles.json"] with(format='multijson')
| where isnotempty(knownShortestPath) or isnotempty(example)
| project-rename RoleId = id, AttackPathType = pathType, ShortestAttackPath = knownShortestPath, AttackPathExample = example;
let PrivilegedUsers = IdentityInfo
| where TimeGenerated > ago(14d)
| summarize arg_max(TimeGenerated, *) by AccountObjectId
| mv-expand AssignedRoles
| extend RoleName = tostring(AssignedRoles);
SensitiveEntraDirectoryRoles
| join kind=inner ( PrivilegedUsers ) on RoleName
| extend RoleAssignment = bag_pack_columns(AccountName, AccountUPN, UserType, Tags, IsAccountEnabled, RiskState)
| summarize RoleMembers = count(), RoleAssignments = make_list(RoleAssignment), RiskState = make_list(RiskState), UserType = make_list(UserType) by RoleName, RoleId, tostring(Categories), tostring(EntraOpsCategory), isPrivileged, tostring(EntraOpsClassification), tostring(RichDescription)
| extend RiskyAdmins = iff(RiskState has "atRisk", true, false)
| extend GuestAsAdmins = iff(UserType has "Guest", true, false)
| project-reorder RiskState, RoleName, RichDescription, EntraOpsClassification, isPrivileged, EntraOpsCategory,Categories, RoleMembers, RoleAssignments
| sort by RoleName asc
| join kind=inner ( KnownAttackPaths) on RoleId
| project-away RiskState, UserType, RoleId1
// Filter for risky or external users only
| where RiskyAdmins = true or GuestAsAdmins == trueExplanation
This query is designed to generate a comprehensive list of sensitive directory roles in an Azure environment, enriched with various details and classifications. Here's a simplified breakdown of what the query does:
-
Load Sensitive Directory Roles: It fetches a list of directory roles from an external JSON file, including details like role name, ID, categories, descriptions, and classifications.
-
Filter and Expand Roles: It filters out unclassified roles and expands the role permissions to categorize them.
-
Load Known Attack Paths: It fetches known attack paths for these roles from another external JSON file, renaming and projecting relevant fields.
-
Fetch Privileged Users: It retrieves information about privileged users from the
IdentityInfotable, focusing on users who have been active in the last 14 days. -
Join Roles with Users: It joins the directory roles with the privileged users, creating a detailed list of role assignments, including flags for risky users and guest users.
-
Summarize and Extend Data: It summarizes the data to count role members and includes additional flags for risky admins and guest admins.
-
Filter and Sort: Finally, it filters the results to include only roles with risky or guest admins and sorts the list by role name.
In essence, the query provides a detailed and filtered list of sensitive directory roles, highlighting those with potential security risks due to the presence of risky or guest users.
Details

Thomas Naunheim
Released: August 8, 2024
Tables
Keywords
Operators