Skip to content

AD-PATH-001: Control paths from non-tier-0 principals to tier 0

high   Attack paths   MITRE ATT&CK T1098, T1484   Reads: derived from other findings

Principals outside tier 0 have a chain of memberships, ACLs, GPO, certificate or delegation rights that ends in control of tier 0.

Also known as: attack-paths, tier0-paths

Why it matters

Single checks look at one object at a time. Attackers do not: they chain whatever they find. A help desk group with reset password on a server admin, who is local admin on the Entra Connect server, which holds the sync account's password, which can DCSync, is four ordinary-looking delegations and one domain compromise.

Any principal with such a chain is tier 0 whether or not it is in an admin group: its password, its sessions and every machine it logs on to are as valuable as a domain admin's. Attack tools such as BloodHound find these paths in minutes.

How ad-doctor detects it

ad-doctor builds a control graph from the snapshot, without a graph database. An edge A -> B means A controls B or can become B:

Edge Source
member of group member, including memberships a GPO writes through the DCs
owns, takeover rights (full control, write/WriteDacl/WriteOwner, write msDS-KeyCredentialLink, reset password, ...) owner and ACEs on users, computers, groups, OUs and the domain head
... (inherited), contains inheritable ACEs on OUs and containers, and control of a container over what is below it; AdminSDHolder-protected objects are excluded
DCSync both replication rights on the domain head
link GPOs, linked to domain write access to gPLink, and GPO links to the domain or the Domain Controllers OU for a GPO that reaches a writable DC
GPO applies to, GPO inherited by, GPO reaches whoever can write a GPO controls what it applies to: from the GPO through its links on OUs, the domain head and sites, down the OU tree to computers and users
admin to via GPO ... local administrator (or equivalent) groups set by Group Policy; admin on a computer becomes that computer account
hosts sync account an Entra Connect server holds its sync account's password
enroll (ESC1-3), write template (ESC4), full control on PKI objects, ManageCA (ESC7) certificate templates, PKI containers and CA permissions
read gMSA password msDS-GroupMSAMembership

Tier 0 is the built-in admin and operator groups, domain controllers, krbtgt, the domain head, the Domain Controllers OU, AdminSDHolder, CA servers and the PKI objects. A reverse breadth-first search from tier 0 gives the shortest path from every other principal.

Each object is one principal that holds a right itself, with its shortest path, broad groups first, for example:

Domain Users -[enroll (ESC1-3)]-> template LabESC1
LabServerAdmins -[admin to via GPO LabLocalAdmins]-> ENTRA01$ -[hosts sync account]-> MSOL_0a1b2c3d4e5f -[DCSync]-> corp.example

GPO reach follows Group Policy, not containment. Disabled links, Block Inheritance and Enforced count, because they sit on the OU and the writer of a GPO cannot change them. What sits on the GPO does not hold its writer back: a disabled computer or user side stays in the graph, with a caveat in the path text, because the writer can flip the flags attribute. A security filter stops a writer of values, but not one who owns the GPO or can rewrite its DACL: that path runs through a node GPO ... with its filter changed. A filter naming a group the snapshot does not hold (another domain's, or one not readable) cannot be judged, so the GPO is assumed to apply, with a caveat and a note naming it. Since MS16-072 Windows fetches user policy as the computer, so user-side reach also needs some computer to be able to read the GPO.

A GPO that reaches only a read-only DC gets no linked to domain edge, because an RODC cannot write the domain; an RODC itself counts as tier 0, so the path to it stays. A GPO reaches computers and users, not groups or the OU itself, and it does reach objects with inheritance disabled. The steps between the GPO and the account are scope nodes such as users under Lab:

gpo_editor -[full control]-> LabOuReach -[GPO applies to]-> users under Lab -[GPO reaches]-> svc_sql

Members who only inherit a path through a group are counted in the detail ("19 of 20 enabled users (95%) have a path") instead of being listed. Remote logon rights a GPO grants (RDP, WinRM, DCOM) are exported to BloodHound but not followed, because logon is not control.

Attributes and probes read
  • member
  • nTSecurityDescriptor (owner, ACEs, inheritable ACEs)
  • gPLink
  • GPO local group settings in SYSVOL
  • certificate template and CA ACLs
  • msDS-GroupMSAMembership

Severity

Always high: every path reported ends in control of a tier-0 object, so the start of the path is in effect tier 0. The detail adds when a broad group (Domain Users, Authenticated Users, Everyone and similar) has a path, which makes every user tier 0.

False positives and limits

  • Intended delegations into tier 0, such as the Entra Connect sync account's DCSync right. The path is real; the fix is to treat the start of it as tier 0 (see AD-PRIV-011). Accept it only after that, in an accepted-risk file.
  • Local accounts and local groups on servers are invisible over LDAP, so paths through them are missed rather than over-reported; the same goes for sessions and logons.
  • GPO reach assumes WMI filters match (the path shows the caveat), ignores Deny ACEs on the GPO, and assumes a user in scope logs on somewhere. Empty GPOs and disabled sides count, because the writer fills them in or turns them on. It can also miss: loopback processing is not modelled, and with more than one site, site links are followed only to the domain controllers of that site (the scan says so in a note). A DC whose site is unknown counts as reached, with a caveat.
  • Deny ACEs that cancel an allow are not modelled; a reported ACL step may be blocked in practice. Confirm with the steps below before removing a right in a hurry.

Fix

  1. Start with broad groups and the shortest paths. A path from Domain Users or Authenticated Users makes every account tier 0, so it comes first in the list.

  2. See what one principal can reach, from a saved snapshot:

    ad-doctor collect dc01.corp.example --ldaps -u 'CORP\auditor' -o snap.json
    ad-doctor blast-radius snap.json helpdesk
    
  3. Break each path at its first step: remove the ACE, the group membership, the GPO edit right, the template enrollment right or the local admin grant that starts it. The single check named in the step usually says how, for example AD-ACL-004, AD-GPO-006 or AD-ADCS-001. Review an ACE before removing it:

    (Get-Acl 'AD:CN=Server Admins,OU=Groups,DC=corp,DC=example').Access |
        Where-Object IdentityReference -like '*helpdesk*'
    
  4. Where the step cannot be removed, promote its start to tier 0: move the account or server under tier-0 administration, with the same logon restrictions as domain admins.

  5. Explore the graph in BloodHound when many paths share steps:

    ad-doctor export-graph snap.json -o graph.json --paths-only
    

See BloodHound export.

Verify

ad-doctor scan dc01.corp.example --ldaps -u 'CORP\auditor' --only AD-PATH-001

To accept the risk instead, add an entry to the file passed with --accept (see accepted risks):

[[accept]]
check = "AD-PATH-001"
objects = ["..."]        # optional; without it the whole check is accepted
reason = "..."
expires = 2027-03-31

References

Microsoft and vendors

Research

Tools

MITRE ATT&CK

Available since 0.1.0.