Home Kerberos IV - Delegations
Post
Cancel

Kerberos IV - Delegations

Kerberos IV - Delegations

The third and smartest Cerberus head

In the third part of this Kerberos series, we focused on leveraging user credential material for impersonation through techniques such as Pass-the-Key/Ticket/Cache/Certificate, and Shadow Credentials. Additionally, we explored how to manage and forge Kerberos tickets to facilitate lateral movement, privilege escalation, and establish persistence within the domain.

In this fourth post, and last of the series, we will explore Kerberos delegations.

There are many great articles about delegations, even though the abuse of this feature is an old attack vector, here at Lares, we wanted to deep dive and analyze the whole flow of what Kerberos delegations entail. In this post, we’ll review the different types of delegation, providing a detailed understanding of their use cases and potential security implications.

While this post primarily focuses on the functionality of Kerberos delegations and abuse cases, we have also included brief notes and best practices for detecting potential abuses and misconfigurations, which will in turn help to enhance security postures against these risks.

Note: In each delegation scenario, the communication flow will be analyzed. For a review of the Kerberos communication process, refer to the first post in this series.
Kerberos I - Overview.


Kerberos Delegations

Microsoft introduced the Kerberos delegation feature with the first implementation of Active Directory in Windows 2000. Defined by Microsoft, Kerberos delegation is a setting that allows applications to request end-user access credentials to access resources on behalf of the originating user.

This feature was intended to solve the double-hop issue. ‘Double Hop’ issues can occur when a user needs to access a resource on a second server through an initial server. After authenticating to the first server (Server A), the user’s credentials are used to get a service ticket for Server A; however, when Server A needs to access resources on Server B on behalf of the user, it faces a problem because it cannot use the user’s credentials or tickets to authenticate to Server B.

This prevents proper authentication on the second hop, resulting in access failures.

Below is a classic example of a basic double-hop scenario and would be why delegation is necessary:

  • The user Elliot.A wants to access company documents, so he authenticates with his domain credentials on the web application hosted on the server DEV.Lareslabs.local. This application runs in the context of its own service machine account (DEV$).
  • The folder that the web application has to retrieve is located on another server shared path (\\FS1\Data) and this folder has the following security descriptor, defining access rights for Elliot.A, and other ACEs that do not grant access to DEV$:

FS1\Data folder security descriptor

  • When the web application tries to retrieve the files through the CIFS service on the FS1 server, it will do so under its context and will not have access, preventing Elliot.A from accessing the files through the web application:

Kerberos double-hop issue

  • Kerberos delegation helps solve this problem, in the following example, DEV.lareslabs.local (DEV$) is configured with unconstrained delegation (the most insecure kind of delegation, which we will see next), so it can gain access to the shared folder impersonating Elliot, using Elliot’s Kerberos Tickets as proof that it has permission to impersonate, then placing a copy of the user token in a new thread of its executing process so that thread can act on behalf of Elliot.A and is subject to the restrictions imposed by ACLs:

Kerberos Delegation

There are three kinds of delegations:

  • Unconstrained Delegation.
  • Constrained Delegation, (Kerberos Only and Protocol Transition).
  • Resource-based Constrained Delegation (RBCD).

Note: The ASP.NET Core Web API application KerbApp by @_RastaMouse has been used for the lab configuration. The application allows the authentication scheme to be configured through HTTP.sys.


Unconstrained Delegation

Unconstrained Delegation allows an entity to impersonate a Principal to any chosen service. When this delegation is configured in a service, the client delegates a copy of its TGT to this service, so this service can act on behalf of the client in the network by using that TGT.

So, it allows an attacker who has gained control of a domain account configured with delegated permissions to impersonate any user or service within the domain.

To configure graphically, it is required to enable the option “Trust this computer for delegation to any service (Kerberos only)”:

Unconstrained Delegation configured on DEV

Using the PS Active Directory module, it is possible to verify whether an account is configured with Unconstrained Delegation by checking the attribute "TrustedForDelegation":

Unconstrained enumeration using Get-ADComputer function

To better understand this kind of delegation, let’s examine step-by-step the traffic generated during the scenario described above:

  1. The user Elliot.A wants to access company documents, so he authenticates using his domain credentials on the web application hosted on the server DEV.lareslabs.local. Since DEV$ does not have direct permissions to access these files, which are hosted on another server called FS1.lareslabs.local, it is configured with unconstrained delegation. This allows it to impersonate Elliot.A and access the files on his behalf.

Unconstrained Delegation flow

The following shows Elliot.A performing an HTTP request to DEV webapp:

HTTP request

Using Wireshark to capture and review this network traffic, we will be able to identify the following network flow:

Unconstrained Delegation network traffic

Let’s break things down step by step:

  • Step 1: The client, Elliot.A, requests a TGT from the KDC; if credentials are valid, the KDC will return the TGT—just the normal Kerberos flow (AS-REQ / AS-REP).
  • Step 2: The client requests an HTTP Service Ticket (HTTP/DEV.lareslabs.local) in the first TGS-REQ, sending his TGT and authenticator:

HTTP/DEV.lareslabs.local TGS-REQ

  • Step 3: The KDC provides the Service Ticket with the ok-as-delegate flag set, indicating that the requested service is configured to allow delegation:

ok-as-delegate flag

  • Step 4: Since the client verified that the target service is enabled for delegation, it will send a new TGS-REQ request for an additional Service Ticket (Elliot.A’s TGT), again sending its TGT and Authenticator—but this time requesting a copy of his TGT with the forwarded flag set:

Forwarded TGT request

  • The ticket-granting service (TGS) then provides a (delegated) TGT with the forwarded flag, the KDC expects this request as a follow-up of the previous one, as the service is configured with Unconstrained Delegation:

TGS-REP, TGT with forwarded flag

  1. Once with a forwardable TGT, the client will perform an AP-REQ message within the HTTP request, sending the service ticket for the HTTP service in addition to the delegated TGT. The forwardable TGT is contained within the HTTP request:

HTTP request

  1. The web server, (DEV$), uses the client’s cached TGT to request a Service Ticket from the KDC for the CIFS/FS1 on behalf of Elliot through a regular TGS-REQ message:

TGS-REQ regular TGS-REQ on behalf of Elliot.A

The KDC provides a valid Elliot.A Service Ticket for CIFS/FS1 service to DEV$:

TGS-REP

  1. DEV$ will send an AP-REQ message via SMB on behalf of Elliot.A, sending the CIFS service ticket and the authenticator:

AP-REQ, mutual authentication

FS1$, will in turn, perform a mutual authentication process with DEV$, via SMB, through an AP-REP message:

AP-REP, mutual authentication

  1. Finally, the client (Elliot.A) and DEV$ will complete the mutual authentication process via an AP-REP message over HTTP, resulting in displaying the FS1$ shared files that the client wanted to access:

AP-REP through HTTP, mutual authentication

Abusing Unconstrained Delegation

As we already know, any principal connecting to a machine configured with unconstrained delegation will drop a copy of its TGT in memory.

From a threat actors’ stance, the objective will be to gain privileged access to these servers and dump these delegated TGTs that are cached in memory. Alternatively, they/we can force the authentication of a privileged account against this machine, to obtain clients’ delegated TGTs.

From Linux, the first step will be adding a “fake” spn pointing to our listener, our attacker machine. To do this, addspn can be used, as machine accounts can edit their own msDS-AdditionalDnsHostName attribute.

It is also required to create a DNS record with the name of the fake registered spn pointing to the attacking machine, dnstool from @_dirkjan’s krbrelayx suite can be used to perform this operation.

Finally, krbrelayx will be used, in conjunction with the Kerberos key or the password and salt of the account configured with Unconstrained Delegation that has been compromised, forcing authentication with the chosen method. In this example, Coercer:

krbrelayx & coercer

Once the delegated TGT (.ccache) is obtained, it can be exported and used to impersonate that coerced account:

secretsdump using delegated TGT

From Windows computers, the Rubeus monitor function performs the same role. After forcing authentication with the desired method, the cached .kirbi in memory can be obtained and used for impersonation.


Constrained Delegation

Kerberos Constrained Delegation, introduced in Windows Server 2003, aims to provide a safer form of delegation that could be used by services.

While Unconstrained Delegation allows the impersonation of any domain principal on any network service, for accounts configured with Constrained Delegation, target services are limited by configuration. This approach enhances security by limiting the scope of delegation to only explicitly allowed services, thus minimizing potential exposure from compromised services.

In addition, in Constrained Delegation, it is not necessary to have a user’s TGT within the TGS request. The service itself can request service tickets for other services on behalf of a user as long it has proof that it has received a request from the user.

For this purpose, Microsoft issued the S4U MS-SFU extension that allows the KDC to issue a new TGS to the service using a valid TGS through two subprotocols, S4U2Self and S4U2Proxy.

  • S4U2Self: allows a service to obtain a service ticket to itself on behalf of a user.
  • S4U2Proxy: allows a service to obtain a service ticket on behalf of a client to a different service using a service ticket as evidence that the client has authenticated.

Constrained delegation can be configured to accept only Kerberos authentication, or other protocols, such as NTLM, in scenarios where Kerberos authentication is not possible.

Kerberos Only:

A visual depiction of the Constrained Delegation configuration, using Kerberos only, can be seen in the image below. In this instance it is configured for only delegation allowed for FS1.lareslabs.local CIFS service:

Constrained Delegation configured on DEV

Following the same scenario, but now, DEV$ configured with Constrained Delegation and Kerberos Only:

Constrained Delegation - Kerberos Only Flow

  1. Kerberos pre-auth, usual flow, obtaining a TGT via AS-REQ/AP-REP messages.
  2. The client (Elliot.A) requests a service ticket for HTTP/DEV.lareslabs.local (TGS-REQ message). Then, the KDC provides the service ticket through the TGS-REP message.
  3. The client sends an HTTP AP-REQ message to the web server, including the service ticket within the request.
  4. Through the next TGS-REQ message sent by DEV$ to the KDC, the service can request additional service tickets using an S4U2Proxy request. Through this extension, the web server will send a request to the KDC for a CIFS/FS1.lareslabs.local service ticket sending its TGT and authenticator and the previous HTTP/DEV service ticket from Elliot.A, within the “additional tickets” block:

CIFS - TGS-REQ (S4U2Proxy)

In the following image, it is shown how, in the same request, the client (DEV$), requires the KDC to check if the constrained delegation is configured and viable:

TGS-REQ constrained delegation flag

The KDC will check the additional ticket, verify that it is forwardable, and further verify that DEV$ can delegate to FS1$, by checking the msDS-AllowedToDelegateTo an attribute:

DEV$ msDS-AllowedToDelegateTo attribute

Forwarding Elliot.A’s CIFS/FS1 ST + Session Key through the TGS-REP response to DEV$:

TGS-REP (S4U2Proxy)

  1. DEV$ requests CIFS access to FS1$ on behalf of Elliot.A through the AP-REQ message and FS1$ will reply to DEV$, performing the mutual authentication process via the AP-REQ message.
  2. Finally, the web application will return the information retrieved for Elliot.A through an AP-REP message via HTTP (Mutual authentication between the DEV$ and Elliot.A):

HTTP AP-REP

Abusing KCD Kerberos Only:

Kerberos Only requires an additional ticket as a requirement to invoke S4U2Proxy. The first approach should be user S4U2Self but required TRUSTED_TO_AUTH_FOR_DELEGATION flag set, which is not True, since Kerberos Only was used and the resulting ST will be non-forwardable.

Although it is possible to abuse Kerberos Only through the “bronze bit” (CVE-2020-17049) technique or by forcing authentication, the most direct method would be through RBCD. To abuse this, it is first necessary to use an indirect method that exploits Resource Based Constrained Delegation first.

Protocol Transition:

In Constrained Delegation Kerberos Only, the service can invoke S4U2Proxy using Elliot.A’s service ticket (ST) as an additional ticket; however, if the service does not have this additional ticket, such as via NTLM authentication, it needs another way to obtain proof (a ticket) that the client is delegating on its behalf. In this case, a service can invoke S4U2Self to ask the authentication service to produce a TGS for arbitrary users to itself, which can then be used as “evidence” when invoking S4U2Proxy.

This feature allows impersonating users on an ad-hoc basis, and it is only possible when the TrustedToAuthForDelegation flag is set for the service account that invokes S4U2Self.

Protocol Transition - Constrained Delegation, DEV$

Following the same scenario, with DEV$ configured with Constrained Delegation and Protocol Transition, the flow looks as follows:

Constrained Delegation - Protocol Transition Flow

  1. Client Elliot.A will send an HTTP request to the DEV web server. Authentication will be performed using NTLM since the application does not accept Kerberos:

NTLM authentication

  1. To get CIFS/FS1 service ticket (using the S4U2Proxy request) DEV$ has to provide a proof, a service ticket from the user. Since there is no service ticket provided by Elliot.A (NTLM authentication was used) the server should ask for it using the S4U2Self extension.

In the TGS-REQ message that DEV$ will send to the KDC, the structures specific to the S4U2Self extension, pA-FOR-X509-USER, and pA-FOR-USER are present, with the name as the client to impersonate (Elliot.A) and its’ own SPN, e.g. the DEV$ target spn:

TGS-REQ (S4U2Self)

The KDC will then verify that DEV is configured with constrained delegation enabled (TRUSTED_TO_AUTH_FOR_DELEGATION) and will provide a service ticket on behalf of Elliot.A with the forwardable flag set to True through the TGS-REP message:

TGS-REP (S4U2Self)

  1. DEV sends its TGT, an authenticator, and the S4U2Self additional ticket, asking the KDC for a CIFS/FS1 service ticket:

TGS-REQ (S4U2Proxy)

Here is the difference from the classic constrained delegation: the KDC checks:

  • If FS1$ is listed in DEV$ msDS-AllowedToDelegateTo. Since RBCD has been configured and not KCD, Constrained Delegation cannot be applied.
  • Then, as a “fallback” if DEV$ is listed in msDS-AllowedToActOnBehalfOfOtherIdentity attribute of FS1$. RBCD can be applied.
  1. DEV request CIFS access to FS1 on behalf of Elliot.A through the AP-REQ message and FS1 will reply DEV, performing the mutual authentication process via the AP-REQ message.
  2. Finally, the web application will return the information retrieved for Elliot.A through an AP-REP message via HTTP (Mutual authentication between the DEV and Elliot.A).
Abusing RBCD:

Having write rights on the target msDS-AllowedToActOnBehalfOfOtherIdentity attribute enables the configuration of Resource-Based Constrained Delegation (RBCD). Exploiting this trust requires an account capable of invoking both S4U2Self and S4U2Proxy, though, fortunately, any account with a configured SPN can invoke these extensions, allowing for the impersonation of any user against the services tied to the affected service account.

The quickest way is to create a machine account, as demonstrated in the following example by using PowerMad:

Powermad New-MachineAccount

Next, the msDS-AllowedToActOnBehalfOfOtherIdentity attribute in DEV will be edited with the new machine account:

Editing msDS-AllowedToActOnBehalfOfOtherIdentity using Powerview

Rubeus s4u function requests the delegated ST, specifying an SPN pointing to our target and a user to impersonate, using the new machine account credentials:

Rubeus S4u

The resulting ticket will be forwardable:

Rubeus describe function

Use that service ticket as proof of authentication in S4U2Proxy for FS1$:

Rubeus S4U & PTT

Through pass-the-ticket, access to the target service will be granted:

PTT access granted

From Linux, the process would be the same, easily replicable using impacket, addcomputer, rbcd.py and getST.

Useful Defenses:
  • Enable AccountNotDelegated (Account is sensitive and cannot be delegated) UAC flag on your Tier-0 accounts.
  • Identify all the servers that have delegation configured and change to constrained delegation whenever possible.
  • Add user accounts to the Protected Users Security Group.
  • Sigma rule for unconstrained delegation (PS-Enumeration).
  • Relevant events: 4769 - 5156 - 4624 - 5140 - 5145 - 4675 - 4672 - 4673 - 4611 - 5136.
  • Techniques (MITRE ATT&CK) - T1589.002, T1018, T1550.003, T1078.002, etc.

We hope you enjoyed this Kerberos series, and that the series will continue to serve as a reference for your Kerberos queries.
Finally, thank you for reading it!


Resources

  • Specterops - Hunting in active directory : Unconstrained Delegation. (link)
  • Atl4s - Understanding - or at least, trying to. (link)
  • Dirk-Jan Mollema - Having fun with unconstrained delegation. (link)
  • Harmj0y - S4U2Pwnage.Another word of delegation. (links, link).
  • Elad Shamir - Wagging the dog, abusing RBCD. (link)
  • Charlie Clark - Abusing Users Configured with K-UD. (link)
  • Charlie Bromber - Bypass Kerberos Delegation. (YouTube link)
  • Splunk - Detecting Active Directory Kerberos Attacks. (link)
  • Luemmelsec - A low dive into Kerberos Delegations. (link)
  • Swolfsec - Detecting RBCD. (link)
This post is licensed under CC BY 4.0 by the author.