ADKERB-004: Unconstrained Delegation - Computers

Platform
Active Directory
Category
AD Kerberos Security
Severity
Critical
Zero Trust pillar
Identity (weight 3)
Golden fixtures
3
Branch coverage
Observed: fixtures prove the verdicts they exercise
Provenance
baseline

What it checks

The check binds to each domain in the forest and issues an LDAP query for (&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288)) where 524288 is the TRUSTED_FOR_DELEGATION (ADS_UF_TRUSTED_FOR_DELEGATION) bit. For every returned object it reads sAMAccountName, distinguishedName, dNSHostName, operatingSystem, primaryGroupID, msDS-AllowedToActOnBehalfOfOtherIdentity, lastLogonTimestamp, and the SPN list (servicePrincipalName). It then suppresses domain controllers (primaryGroupID 516 or membership in the Domain Controllers group, plus RODCs identified by primaryGroupID 521) because the DC role inherently requires unconstrained delegation to function. Every remaining computer object becomes a finding. The check also resolves whether the account has the ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit (0x1000000) so it can distinguish unconstrained (full TGT delegation, this check) from constrained with protocol transition (ADKERB-005). Finally it records whether each host is reachable on TCP 445 and whether the Print Spooler service is responsive on TCP 135 / named pipe, both of which are common coercion preconditions.

Why it matters

Unconstrained delegation is the single most dangerous Kerberos misconfiguration outside of compromising the KDC itself. When a user authenticates to a service running on a TrustedForDelegation host, the user TGT (encrypted with krbtgt, valid for 10 hours by default, renewable for 7 days) is forwarded inside the service ticket and cached in LSASS by the receiving service so it can perform delegated calls. Any code running as SYSTEM on that host (a vulnerable web app, a hijacked agent, a local admin, a backup operator) can dump those tickets and impersonate the original principal forest-wide. The blast radius is not theoretical: an attacker does not have to wait for a Domain Admin to log on. The SpoolSample / PrinterBug coercion (Lee Christensen, 2018) and the MS-EFSR PetitPotam coercion (Gilles Lionel, 2021) let any authenticated principal force a domain controller computer account to authenticate to an attacker-chosen host, including a host the attacker controls because it is configured with unconstrained delegation. Within seconds the attacker holds DC$ TGTs and can perform DCSync against the domain. Microsoft documents this as a critical configuration to remediate, and Protected Users / "Account is sensitive and cannot be delegated" are explicit mitigations precisely because the attack path is so reliable.

Attack path

Step 1: Discovery. The attacker, holding any low-privilege foothold, queries LDAP for (userAccountControl:1.2.840.113556.1.4.803:=524288) and excludes the Domain Controllers OU. PowerView Get-DomainComputer -Unconstrained, BloodHound (Unconstrained Delegation edge), or the ADKERB-004 output give the same list. Any reachable non-DC in the list is a target. Step 2: Foothold on the unconstrained host. The attacker compromises the unconstrained computer through any normal path: a stale local admin password (LAPS not deployed), a Kerberoastable service account that runs on the host, an exposed RDP, a vulnerable application, or an existing agent foothold. SYSTEM is sufficient; LocalAdmin works because privilege can be elevated to SYSTEM via PsExec, Scheduled Tasks, or Service creation. Step 3: Coercion. The attacker enables ticket monitoring on the compromised host with Rubeus monitor /interval:5 /nowrap or Mimikatz sekurlsa::tickets /export. From any authenticated context (the same low-priv foothold) the attacker triggers a coercion against the target DC. SpoolSample.exe DC01 UNCONSTRAINED-HOST forces DC01$ to authenticate via the MS-RPRN PrinterBug. If Print Spooler is disabled on DCs, the attacker falls back to PetitPotam.py UNCONSTRAINED-HOST DC01 over MS-EFSR, DFSCoerce.py over MS-DFSNM, or the MS-FSRVP "ShadowCoerce" primitive. All four force a Kerberos AP-REQ from the DC machine account to a CIFS or HTTP SPN on the unconstrained host. Step 4: TGT capture. Because the host is TrustedForDelegation, the DC includes a forwarded TGT in the service ticket. Rubeus captures it (base64-encoded krbtgt-issued ticket for DC01$). On disk it is a .kirbi file; in memory it is visible to sekurlsa::tickets. Step 5: DCSync. The attacker injects the captured DC01$ TGT with Rubeus ptt /ticket:<base64> and runs mimikatz lsadump::dcsync /domain:contoso.local /user:krbtgt or secretsdump.py -k DC01.contoso.local. The DC machine account holds the Replicating Directory Changes and Replicating Directory Changes All extended rights by virtue of being a domain controller, so the request succeeds. The attacker now holds the krbtgt hash and can forge Golden Tickets for any principal in the domain. Total elapsed time from foothold on the unconstrained host to krbtgt: typically under five minutes.

How Guerrilla assesses it

Guerrilla performs a single LDAP search per domain in the forest using the bitwise-AND OID matching rule 1.2.840.113556.1.4.803 against userAccountControl with the value 524288 (TRUSTED_FOR_DELEGATION). For each returned computer object it pulls userAccountControl, primaryGroupID, sAMAccountName, dNSHostName, operatingSystem, operatingSystemVersion, lastLogonTimestamp, servicePrincipalName, msDS-AllowedToActOnBehalfOfOtherIdentity, and whenChanged. Computer accounts whose primaryGroupID equals 516 (Domain Controllers) or 521 (Read-Only Domain Controllers) are filtered out and recorded as expected. Every remaining account is rendered as a Critical finding because the configuration is exploitable by design. The check enriches each finding with: whether the host responds on TCP 445 (likely target of CIFS coercion), whether the Print Spooler service answers on the MS-RPRN named pipe (PrinterBug exposure), the SPN list (useful for understanding which services would receive forwarded TGTs), and a stale-account flag if lastLogonTimestamp is more than 90 days old (a dormant unconstrained host is still exploitable if it can be powered on). The check does not require Domain Admin; a normal authenticated user can read userAccountControl on computer objects.

Recommended value

No computer accounts with unconstrained delegation except domain controllers (which inherently require it). All other delegation migrated to constrained or resource-based constrained delegation

Remediation

Identify computers with unconstrained delegation using Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation. Exclude domain controllers from findings. For remaining computers, migrate to constrained delegation by identifying the specific services they need to delegate to, then configure msDS-AllowedToDelegateTo. Add sensitive accounts to the Protected Users group to prevent their TGTs from being cached. Mark high-value accounts as 'Account is sensitive and cannot be delegated'

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.

Verdict scenarios for ADKERB-004
ScenarioExpected verdict
cleanPASS
known-badFAIL
throttledNot Assessed

Framework mappings

NIST SP 800-53
AC-6
ANSSI
R35
CIS AD Benchmark
7.3.1
MITRE ATT&CK
T1558.001