Active Directory is walked, not exploited: BloodHound edges, Kerberoasting and ADCS ESC1
Domain compromise is almost never a memory-corruption bug. It is a graph traversal across permissions somebody granted on purpose. Here are the three routes that keep working, and what to check tonight.
8 min read7 views
The mental model most people bring to Active Directory security is the one they learned from CVEs: find the unpatched thing, exploit the unpatched thing, get shell.
That is not how domains fall. In the overwhelming majority of real compromises, nothing is exploited in the memory-corruption sense at all. Every permission used was granted deliberately by an administrator, every protocol behaved as designed, and every step was an ordinary operation performed by an account entitled to perform it.
Active Directory compromise is a graph traversal problem. The path from an ordinary user to Domain Admin already exists in your directory right now. The attacker's work is not creating it. It is finding it before you do.
That reframing is the single most useful thing to take from this post, because it changes what you go and look at on Monday.
The graph is the product
AD is a directory of objects with permissions between them. Model it as a graph, users, groups, computers as nodes; permissions and sessions as directed edges, and "can this user become Domain Admin?" becomes a pathfinding query.
That is precisely what BloodHound does. It collects the objects and their relationships and answers the shortest-path question directly. It is defensive tooling as much as offensive: the same query that shows an attacker their route shows you what to sever.
The edges that matter most in practice:
| Edge | What it means | Why it ends badly |
|---|---|---|
MemberOf | Group membership | Nested groups mean people hold rights nobody remembers granting |
AdminTo | Local admin on a host | Local admin plus a privileged session equals that session's credentials |
HasSession | An account is logged on here | The reason lateral movement works at all |
GenericAll / GenericWrite | Full or broad write over an object | Reset its password, or edit it into something useful |
WriteDacl / WriteOwner | Rewrite the object's own permissions | Grant yourself whatever you were missing |
AddKeyCredentialLink | Add key credentials to an object | Shadow Credentials, authenticate as it without touching its password |
ForceChangePassword | Reset a password without knowing it | Exactly what it says |
Note how many of those are write permissions rather than membership. This is where real environments come apart: a helpdesk group given GenericWrite over an OU in 2019 for a legitimate reason, never reviewed, now three nested groups deep from everybody.
The question to ask of your own directory is not "who is in Domain Admins?" It is "who can make themselves a Domain Admin, in one step or five?"
Route one: Kerberoasting
Any domain user can request a service ticket for any account that has a Service Principal Name. Part of that ticket is encrypted with a key derived from the service account's password. Request it, take it offline, crack it.
Nothing here is a vulnerability. Requesting service tickets is what Kerberos is for. The weakness is entirely in the password: service accounts historically get long-lived, human-chosen passwords that are never rotated because rotating them breaks something nobody wants to own.
What makes it high-yield is who those accounts tend to be. SQL service accounts, backup agents and monitoring accounts are routinely over-privileged, frequently Domain Admin, "temporarily", years ago.
What to do about it:
- Group Managed Service Accounts (gMSA) where the service supports them. Windows manages a 240-character random password and rotates it. A gMSA is not crackable in any meaningful sense, which removes the route rather than raising its cost.
- Where gMSA is not possible, a genuinely random 25+ character password and a rotation plan.
- Audit which SPN accounts are privileged. This is a one-line LDAP query and it is the highest-value thing in this section.
- AES-only encryption for Kerberos, so RC4-based cracking is off the table.
Route two: AD Certificate Services, ESC1
If you run AD CS, this is the one to check first, because it is common, it is trivial to exploit once present, and it hands over a Domain Admin authentication rather than a password hash.
ESC1 is a certificate template misconfiguration. Three conditions together:
- A low-privileged group,
Domain UsersorAuthenticated Users, can enrol in the template. - Manager approval is not required.
- The template lets the requester specify a Subject Alternative Name.
Put those together and an ordinary user requests a certificate, names Domain\Administrator as the SAN, and the CA issues a certificate asserting they are the domain administrator. They then authenticate with it.
Read that again, because the severity is easy to miss. There is no exploit, no crack, no race. The CA is asked to certify a lie and agrees, because it was configured to. The tooling, Certipy, the Python port of Certify, enumerates vulnerable templates and completes the request in a couple of commands, which is why this shows up in so many reports.
ESC1 is the best-known of a family running to ESC8 and beyond, covering NTLM relay to the CA's web enrolment endpoint, dangerous CA settings, and vulnerable access control on the CA object itself.
What to do:
- Enumerate your templates now. Certipy in its find mode will tell you, and so will PSPKIAudit. Most organisations that run AD CS have never audited the templates that shipped with an installation years ago.
- Require manager approval on any template permitting SAN specification, or remove that permission.
- Restrict enrolment to the groups that genuinely need it.
Domain Usersshould not be enrollable in anything that authenticates. - Turn on CA auditing,
certutil -setreg CA\AuditFilter 127, and restart the service.
Route three: the session
The oldest one, and still how most engagements move. An account is a local administrator on a machine where a more privileged account has an active session. Compromise the first, take the second's credentials from the session, repeat.
This is what AdminTo plus HasSession means on the graph, and it is why local administrator rights are a domain-wide problem, not a workstation problem.
The controls that actually break it:
- LAPS so local administrator passwords differ per machine. Without it, one local admin hash is every machine.
- A tiering model: Domain Admins never log on to workstations, ever. This is the control that makes the whole chain fail, and it is the hardest to implement because it is organisational rather than technical.
- Credential Guard, and Protected Users for privileged accounts.
- Remove standing local admin from users. Most people who "need" it need it four times a year.
What to check tonight
In rough order of yield per minute:
- Run BloodHound against your own directory. Not as an attacker would, as an auditor. Look at the shortest paths to Domain Admins from
Domain Users. Most people are shocked by this the first time, and it is free. - List privileged accounts with an SPN. Every one is a Kerberoasting target.
- Audit AD CS templates for the ESC1 conditions.
- Count your Domain Admins. Then count the ones that have logged on in ninety days.
- Check for accounts with
adminCount=1that are no longer in privileged groups. They carry the leftover ACLs. - Look for
GenericAll/WriteDaclheld by non-tier-0 groups over privileged objects.
Detection
The recurring difficulty is that every step is a legitimate operation, so detection is about pattern and context, not about signatures:
- Event 4769 (service ticket requested) in volume from one account, especially with RC4 encryption where your domain is AES, that is Kerberoasting.
- Event 4887 on the CA, comparing the requester against the SAN on the issued certificate. A mismatch is the ESC1 signature, and it is why the audit filter above matters.
- Event 4768/4769 for certificate-based authentication by accounts that have never used it before.
- LDAP queries returning unusually large result sets from a workstation. Nothing on a normal desktop enumerates every user object in the domain.
- Event 4662 for reads of unusual directory attributes, and any change to a certificate template.
- New SPN registration, group membership changes on privileged groups, and any modification to
AdminSDHolder. - Honeypot accounts. A decoy privileged-looking account with an SPN and a long random password, which no legitimate process ever touches. Any ticket request for it is an alert with essentially no false positives. This is the cheapest high-fidelity AD detection available and almost nobody deploys it.
Take this away
Every route above is an ordinary feature working correctly. Kerberos issuing service tickets. A CA issuing a requested certificate. A session holding credentials so you are not asked to type them again.
That is why patching does not fix Active Directory, and why "we're fully patched" is not an answer to "can somebody become Domain Admin?" The path is made of configuration and delegated permissions, which means the fix is an audit and the detection is behavioural.
Go and look at your own graph. The path is in there.
Further reading
- BloodHound, and its documentation on edge types
- Certipy, enumerating and understanding AD CS misconfigurations
- Microsoft: Active Directory tier model and privileged access strategy
Was this useful?
Comments
Loading comments…