Active Directory and Kerberos trust

A Windows estate is a trust graph with a directory at its centre. Every domain-joined machine trusts the domain controllers to say who a user is, the domain controllers honour each other’s tickets, a forest honours the forests it federates with, and a service accepts the Kerberos ticket presented to it because a key it shares with the directory signed it. Most of this is invisible at the login page and exact in its consequences. Follow an edge nobody meant to be followed and a helpdesk account becomes a domain administrator, not by breaking Kerberos but by using what Kerberos was built to honour.

Delegation: acting as someone else by design

Kerberos delegation lets a service act on behalf of the users who authenticate to it, because a web front end often has to reach a database as the user. Unconstrained delegation is the blunt form: a machine trusted for it caches the ticket-granting tickets of everyone who connects, and a ticket-granting ticket is the user. Constrained delegation limits which services the account may reach, through S4U2Proxy, but whoever controls the account still arrives at those services as anyone they choose. Resource-based constrained delegation moves the setting onto the target object, so write access to a computer’s msDS-AllowedToActOnBehalfOfOtherIdentity attribute is enough to impersonate any user to it. In each case the mechanism is doing exactly what it advertises; the attacker only had to end up on the trusted side of it.

Tickets as portable trust

The directory’s trust in a ticket rests on a key. The krbtgt account’s hash signs every ticket-granting ticket, so anyone holding that hash forges a golden ticket: a ticket-granting ticket for any user, in any group, valid until the key rotates, which in many domains is never. A service account’s hash signs the service tickets for that service, so its hash mints a silver ticket the service honours without ever consulting a domain controller. Neither is a cryptographic break. Each reuses a key that was trusted to sign, lifted from a domain controller or a service host that held it.

Domain and forest trusts

A trust between domains or forests is a standing agreement to honour each other’s principals. The agreement has a direction and a key, and the key can be abused the way krbtgt is: a trust key forges inter-realm tickets. SID history was meant to smooth migrations by letting a moved account keep its old privileges, and where SID filtering is not enforced across a trust, an attacker injects a privileged SID (security identifier) and carries it into the trusting domain. Forest trusts were long treated as a hard security boundary; in practice the boundary holds only as far as SID filtering and selective authentication are actually configured.

The certificate authority inside the directory

AD CS (Active Directory Certificate Services) turns the directory into an identity issuer, and a mis-templated certificate authority hands identities to the wrong people. Where an enrolment template lets the requester name the subject and permits client authentication, a low-privileged user requests a certificate as a domain administrator and logs in as one (the ESC1 pattern). Where the CA’s web enrolment accepts NTLM, a relayed authentication obtains a certificate for the relayed machine (ESC8). The CA is trusted to vouch for identities across the whole forest, so a flaw in one template is a flaw in every account the CA can name. This is where the directory’s trust graph meets the certificate graph.

Reading the graph before touching it

None of these edges is worth anything until the attacker knows which ones exist, and Active Directory is unusually willing to say. Any authenticated user can query the directory over LDAP (Lightweight Directory Access Protocol) for every computer, every group, every account, and the attributes that give delegation away. BloodHound, a tool for mapping directory relationships, collects that from a single domain credential and draws the shortest path from wherever a foothold sits to Domain Admins: which machines a target logs on to, which accounts have delegation set, and who can write to whom. The graph the defender never fully drew is handed over as a query result, and the work becomes choosing an edge rather than finding one.

A control for every edge, all optional

Each edge has a control that closes it, and each control is optional. Unconstrained delegation can be turned off and privileged accounts marked sensitive so their tickets are never cached; the krbtgt key can be rotated twice to void every golden ticket at once; certificate templates can forbid requester-supplied subjects; tiered administration and the Protected Users group can keep the most valuable credentials off the machines most likely to fall. None of it is on by default, all of it is administrative effort, and much of it breaks something that currently works, which is why the delegation set a decade ago is usually still set. The graph gains edges faster than anyone prunes them, and an attacker needs only the one nobody got round to.