ADKERB-006: Constrained Delegation Analysis
- Platform
- Active Directory
- Category
- AD Kerberos Security
- Severity
- High
- Zero Trust pillar
- Identity (weight 2)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check performs an LDAP query against the domain naming context for objects matching (&(objectClass=user)(msDS-AllowedToDelegateTo=*)) and (&(objectClass=computer)(msDS-AllowedToDelegateTo=*)). For each returned object Guerrilla captures the distinguished name, sAMAccountName, objectClass, userAccountControl, the full msDS-AllowedToDelegateTo SPN list, and the values of the TRUSTED_TO_AUTH_FOR_DELEGATION (0x1000000) and TRUSTED_FOR_DELEGATION (0x80000) bits. Each SPN target is then resolved back to its hosting account by joining the SPN against servicePrincipalName attributes on computer and user objects across the domain. Targets that resolve to a domain controller (member of the Domain Controllers group or with the SERVER_TRUST_ACCOUNT (0x2000) and TRUSTED_FOR_DELEGATION (0x80000) bits set in userAccountControl) are flagged High. Service classes are scored independently: LDAP, GC, DRSUAPI, HOST, CIFS, RPCSS, HTTP, WSMAN, and TERMSRV on a DC are flagged Critical because they enable DCSync, file-share access to SYSVOL, WinRM/WMI command execution, or PsExec-style lateral movement. The presence of TRUSTED_TO_AUTH_FOR_DELEGATION (protocol transition, the "Use any authentication protocol" radio button) is captured separately because it removes the requirement for the impersonated user to have actually authenticated to the delegating service, widening the attack surface from S4U2Proxy to S4U2Self plus S4U2Proxy.
Why it matters
Constrained delegation was introduced in Windows Server 2003 to constrain the blast radius of unconstrained delegation, but the constraint only governs which target SPNs the delegated TGS request will succeed against. It does not constrain which users can be impersonated. Any principal trusted for constrained delegation to a service can call S4U2Proxy and request a service ticket for that SPN on behalf of any user in the domain, including Domain Admins, unless the user is flagged "Account is sensitive and cannot be delegated" (userAccountControl bit NOT_DELEGATED, 0x100000) or is a member of Protected Users. A single delegation entry pointing at LDAP/DC01 therefore equals DCSync rights. A delegation entry pointing at CIFS/DC01 equals SYSVOL write, which equals GPO weaponization against the entire domain. A delegation entry pointing at HOST/DC01 covers a large family of SPNs (HOST is an alias) including the schannel, ldap, cifs, and dns SPN classes on that host, meaning HOST is effectively equivalent to "any service on the DC". Even when the target is not a DC, delegation against HOST or CIFS on a Tier 0 jump server or backup server enables a pivot. The risk is compounded by Bronze Bit (CVE-2020-17049, patched November 2020), which let an attacker who controlled the delegating account flip the forwardable flag in the S4U2Self response and bypass the "Use Kerberos only" hardening; only the November 2020 update enforces the bit-flip rejection by default. Resource-based constrained delegation (RBCD), introduced in Windows Server 2012, moves the trust decision to the target resource and is the recommended replacement, but RBCD has its own abuse paths when GenericAll or GenericWrite is held over a computer account (see ADACL checks).
Attack path
Step 1: Discovery. The attacker, holding any domain-authenticated foothold, enumerates principals with a populated msDS-AllowedToDelegateTo using Get-DomainUser -TrustedToAuth (PowerView), bloodhound-python, or Rubeus /list. The output lists each delegating account and its allowed SPN targets. Step 2: Target selection. The attacker picks an entry whose SPN list includes a service on a high-value host, ideally a DC. LDAP/dc01.contoso.com, CIFS/dc01.contoso.com, HOST/dc01.contoso.com, and HTTP/dc01.contoso.com are the canonical targets. Step 3: Credential acquisition. The attacker compromises the delegating account. This is usually a service account, so Kerberoasting (Rubeus kerberoast), password spray, or a previously dumped credential is typical. Cleartext password, NT hash, or AES key all work. Step 4: S4U2Self. Using the delegating account credentials, the attacker requests a service ticket to itself on behalf of a Domain Admin: Rubeus s4u /user:svc_delegate /rc4:<hash> /impersonateuser:Administrator /msdsspn:LDAP/dc01.contoso.com. If TRUSTED_TO_AUTH_FOR_DELEGATION is set (protocol transition), the S4U2Self response is forwardable and the attacker can proceed directly to S4U2Proxy. If only classic constrained delegation is set, the S4U2Self response is non-forwardable, and pre-November 2020 DCs allowed the attacker to flip the forwardable flag via Bronze Bit (CVE-2020-17049) using Rubeus s4u /bronzebit. Step 5: S4U2Proxy. Rubeus chains the forwardable S4U2Self ticket through S4U2Proxy and obtains a service ticket for LDAP/dc01 in the name of Administrator. The ticket is loaded into memory via /ptt. Step 6: Exploitation. With a valid LDAP ticket for Administrator against the DC, the attacker runs secretsdump.py -k -no-pass dc01.contoso.com or mimikatz lsadump::dcsync /user:krbtgt to extract the krbtgt hash and forge Golden Tickets. Alternative payloads by SPN: CIFS yields dir \\dc01\C$ and SYSVOL write for GPO weaponization (see ADGPO checks); HOST and RPCSS yield schtasks and service control; HTTP yields WinRM via Enter-PSSession when WSMAN is also delegated; WSMAN is direct WinRM. The compromise is complete in three to five minutes from initial credential.
How Guerrilla assesses it
Guerrilla binds to the domain naming context over LDAP and issues two filters: (&(objectCategory=person)(objectClass=user)(msDS-AllowedToDelegateTo=*)) and (&(objectCategory=computer)(msDS-AllowedToDelegateTo=*)). For each result the check retrieves distinguishedName, sAMAccountName, userAccountControl, msDS-AllowedToDelegateTo, servicePrincipalName, memberOf, lastLogonTimestamp, and whenCreated. Each SPN in the msDS-AllowedToDelegateTo list is parsed into service class and host components. The host component is resolved against (servicePrincipalName=<service>/<host>*) across the domain to identify the owning computer or service account, and the owning account is tested for membership in the Domain Controllers group, presence of the SERVER_TRUST_ACCOUNT bit (0x2000), and presence of the PARTIAL_SECRETS_ACCOUNT bit (0x4000000) to differentiate writable DCs from RODCs. Service classes are scored by a built-in sensitivity table: Critical for LDAP, GC, DRSUAPI, CIFS, HOST, RPCSS, WSMAN, HTTP, TERMSRV when the host is a writable DC; High for the same service classes against any Tier 0 asset (PKI servers, AADConnect servers, ADFS servers, backup servers) identified from the ADTIER inventory; Medium for any HOST or wildcard alias to any server; Low otherwise. The check separately surfaces accounts where userAccountControl has TRUSTED_TO_AUTH_FOR_DELEGATION (0x1000000) set, because protocol transition removes the requirement for the impersonated user to interact with the delegating service. Findings include the resolved attack chain (delegating principal, target SPN, target host, achievable primitive) so the operator can prioritize remediation.
Recommended value
All constrained delegation entries documented with business justification. No delegation to sensitive services (LDAP, CIFS, HOST, WSMAN) on domain controllers
Remediation
Enumerate constrained delegation using Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne '$null'} -Properties msDS-AllowedToDelegateTo. Review each delegation target. Flag any delegation to DC services (especially LDAP, CIFS, HOST, HTTP, WSMAN) as high risk. Remove unnecessary delegation entries and document legitimate ones with business justification. Consider migrating to resource-based constrained delegation for improved security
Fixture-proven verdicts
Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| known-bad | WARN |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- AC-6
- CIS AD Benchmark
- 7.3.3
- MITRE ATT&CK
- T1550.003