Query Details

Hunt for privilege escalation paths with high ACLs

Hunt Privilege Escalation Paths With High AC Ls

Query

let high_permissions = dynamic(["genericWrite", "genericAll"]);
let edge_labels = dynamic(["member of", "has permissions to", "can authenticate to", "can authenticate as", "has credentials of", "can impersonate as"]);
// Get users and groups with high ACL permissions on other objects
let HighPermissionLinks = (ExposureGraphEdges
    // Get edges related to roles
    | where EdgeLabel == "has role on"
    // Get edges containing high permission ACLs
    | extend Permissions = todynamic(EdgeProperties).rawData.acl.controlTypes
    | where Permissions has_any (high_permissions)
    // Exclude Domain and Enterprise Administrators as source node
    | where not(SourceNodeLabel == "group" and SourceNodeName in ("Domain Admins", "Enterprise Admins"))
    // Exclude Built-in administrator account
    | where not(SourceNodeLabel == "user" and SourceNodeName == "Administrator")
    | summarize TargetNodes = make_set(TargetNodeName), TargetNodeCount = count() by SourceNodeName, SourceNodeLabel, tostring(Permissions), TargetNodeLabel, SourceNodeId
);
let HighPermissionNodes = toscalar(
    HighPermissionLinks
    | summarize SourceNodes = make_set(SourceNodeName)
);
// Get edges for links to the high ACL permissions
ExposureGraphEdges
| where TargetNodeName in (HighPermissionNodes)
| make-graph SourceNodeId --> TargetNodeId with ExposureGraphNodes on NodeId
// Get between one and three relations
| graph-match (SourceNode)-[anyEdge*1..3]->(TargetNode)
    project IncomingNodeName = SourceNode.NodeName, 
    IncomingNodeLabel = SourceNode.NodeLabel,
    Edges = anyEdge.EdgeLabel, 
    OutgoingNodeName = TargetNode.NodeName,
    OutgoingNodeId = TargetNode.NodeId
// Filter for interesting edges
| where Edges has_any (edge_labels)
// Join the high permission ACLs
| join kind=inner HighPermissionLinks on $left.OutgoingNodeId == $right.SourceNodeId
// Exclude Domain and Enterprise Administrators as source node
| where not(IncomingNodeLabel == "group" and IncomingNodeName in ("Domain Admins", "Enterprise Admins"))
// Exclude Built-in administrator account
| where not(IncomingNodeLabel == "user" and IncomingNodeName == "Administrator")
| distinct IncomingNodeName, IncomingNodeLabel, tostring(Edges), OutgoingNodeName, OutgoingNodeLabel = SourceNodeLabel, tostring(Permissions), TargetNodeLabel, tostring(TargetNodes), TargetNodeCount

About this query

Explanation

This query is designed to identify potential privilege escalation paths within an Active Directory (AD) environment by examining Access Control List (ACL) permissions. Here's a simplified breakdown of what the query does:

  1. Define High Permissions: It starts by defining two types of high permissions, genericWrite and genericAll, which are considered risky if granted to certain accounts.

  2. Identify High Permission Links: The query looks for relationships (or "edges") in the AD exposure graph where these high permissions are granted. It specifically focuses on edges labeled "has role on" and checks if they include the high permissions defined earlier.

  3. Exclude Certain Accounts: It excludes well-known high-privilege groups and accounts like "Domain Admins", "Enterprise Admins", and the built-in "Administrator" account from being considered as sources of these permissions. This is because these accounts typically have high privileges by design.

  4. Summarize High Permission Sources: It summarizes the findings by listing which accounts or groups have these high permissions on other objects, along with the count of such target objects.

  5. Graph Relationships: The query then constructs a graph of relationships involving these high-permission nodes, looking for paths that involve one to three relationships.

  6. Filter for Interesting Paths: It filters these paths to include only those with specific types of relationships, such as "member of", "has permissions to", etc., which are considered interesting from a security perspective.

  7. Join and Exclude Again: It joins this information back with the high permission links and again excludes the well-known high-privilege accounts from being considered as sources.

  8. Output: Finally, it provides a distinct list of nodes (accounts or groups) that have high permissions, the types of permissions they have, and the target nodes they can potentially affect.

Overall, this query helps security analysts identify and visualize potential privilege escalation paths in an AD environment, allowing them to take steps to mitigate these risks.

Details

Robbe Van den Daele profile picture

Robbe Van den Daele

Released: May 5, 2025

Tables

ExposureGraphEdgesExposureGraphNodes

Keywords

PermissionsRolesUsersGroupsObjectsNodesAdministratorsAccountDomainEnterpriseEdgesLabelsGraphExposure

Operators

letdynamicwhereextendtodynamichas_anynotinsummarizemake_settostringtoscalarprojectjoinkind=innerdistinct-->withongraph-match

MITRE Techniques

Actions

GitHub