Kerberos Resource-Based Constrained Delegation: a new control path

dim 27/01/2019 - 17:48

This article is part of a series that explore new ways to compromise an Active Directory. The series follows an outstanding paper published by Elad Shamir: “Wagging the Dog - Abusing Resource-Based Constrained Delegation to Attack Active Directory”.

The first article will focus on an AD objects ownership and permissions, the next one will address the backdoor aspect of the new-found persistence technique.


Shamir’s paper briefly explains Kerberos delegations (and you should definitely go read about it), but we would like to add more details on this, regarding other usages of Kerberos extensions he uses: S4U2Self and S4U2Proxy.


This extension enables any server to ask for a TGS on itself for an arbitrary identity. This is done with a TGS_REQ operation where the pre-authentication data contains the desired client identity for the KDC to generate the right ticket. In a traditional TGS_REQ operation, the client identity should be the requestor, so the computer account used by the host itself.

An important note to understand what’s to come, when the TGS service on the domain controller handles the TGS_REQ, it will look at the requestor’s “userAccountControl” attribute and look for the “TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION” bit. The returned ticket will be forwardable only if this bit is set.

Another property of the TGS_REQ is that any authenticated user can request a TGS for any user having a SPN. The retrieved ticket’s flags though won’t be the same depending on the conditions the S4U2Self is performed. This is used in the Kerberoasting attack, already covered quite a lot, e.g. .

Note that S4U2Self is the mechanism used when you run the effective access of a specific user – note that you do not need to enter the credentials of the said user.
Active Directory effective access
Active Directory Effective Access

This extension still uses the TGS_REQ phase of the Kerberos authentication, but the request contains an additional ticket inside (stored in the eponym section of the TGS_REQ). This nested ticket usually can be obtained in two ways.

If the client has been authenticated through Kerberos, the nested ticket used by the server is the service ticket TS. This TS has to be forwardable for it to usually be reusable (although Shamir found one case where it does not seem to matter) and the KDC set it only if the client account can be delegated.

If the client did not authenticate on the server, the server can use aforementioned S4U2Self operation to impersonate the client. Once again, the ticket can be included in the TGS_REQ only if the forwardable bit is set – which is the case when the server has the “TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION” in its “userAccountControl” attribute. The latter scenario is used when the server is configured with the protocol transition (“Use any authentication protocol”).

However, for S4U2Proxy, the server cannot ask a ticket for anybody. The ticket asked needs to be for a SPN listed in the “msDS-AllowedToDelegateTo” attribute (which completes the classic constraint delegation) or the server has to be authorized in the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute.

Objects ownership and permissions
Being owner

To begin on the ownership subject, we have to state a potential well-known truth: the owner of an object has the implicit right to modify the DACL of this object. That means even if there is an explicit deny for the owner not to be able to touch the object, the owner will still have the rights to change permissions.

This is generally true, but an exception exists: positioning a Deny for the OWNER RIGHTS SID (S-1-3-4) in an object’s ACE removes the owner’s implicit control of this object’s DACL.

This rule is one of the bases of Microsoft security model, it applies as well as on Active Directory objects as on the NTFS objects.

Owner user without the right to write to the DACL
Owner user without the right to write to the DACL
Add an ACE in the nTSecurityDescriptor just because RedTeddy is owner
Add an ACE in the nTSecurityDescriptor just because RedTeddy is owner
ACE effectively added to the nTSecurityDescriptor
ACE effectively added to the nTSecurityDescriptor

It is important to understand this point, because applying this on a computer object doesn't automatically give you the control of the host machine. If you can modify the DACL, you can do whatever you want with the computer object in the AD database, but it will not automatically affect the host... unless an attribute is used by the host to authorize its access explicitely. And that's exactly what Shamir has found!

Having only the write property right

Now, let's restrict ourselves to not being owner and having no right except writing to the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute. Can you own the host with only this attribute?

Well that’s one of the points of Shamir’s paper. If you have access to an account with an SPN and have the right to write into the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute of a computer object, you basically can own the object’s host. Having access to an account with an SPN might not be the most difficult part as accounts can create new computers (see the “ms-DS-MachineAccountQuota” attribute on the domain’s root). The computers will have SPNs or, as you will be owner of the computer object, you will have the right to add the right to write into the “servicePrincipalName” attribute, then add SPNs.

For the attack, Shamir first sets the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute on the computer object (here desktop-u2v0mfq) to have the value of the account the attacker controls (e.g. DESKTOP-LOL42XPS$).

Under the hood, in the object’s “nTSecurityDescriptor” attribute, the right to write this attribute is represented as an ACE of the following form (See for more information):

A right in a middle of an SDDL
A right in a middle of an SDDL

In the ACE, the “OA” means it is an “Allow” entry on a subset of the object, “WP” means “Write Property”, the “3f78c3e5-f79a-46bd-a0b8-9d18116ddc79” GUID is the “SchemaIDGUID” attribute of the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute – retrievable in the schema partition – and the “S-1-5-21-2985693341-697491136-3488640750-1105” SID is the user – the security principal – on which the ACE applies, called the trustee. So basically, this entry allows the domain user which RID is 1105 to write the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute, which is exactly what we need.

Now to effectively use the right and change the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute’s value, the “Set-ADComputer” cmdlet from the ActiveDirectory PowerShell module can be used:

Add DESKTOP-LOL42XPS$ into desktop-u2v0mfq’s msDS-AllowedToActOnBehalfOfOtherIdentity
Add DESKTOP-LOL42XPS$ into desktop-u2v0mfq’s msDS-AllowedToActOnBehalfOfOtherIdentity

Performing this attribute change enables the DESKTOP-LOL42XPS$ account to first request a non-forwardable TGS for any user for itself using S4U2Self, and then use the retrieved TGS with the S4U2Proxy component with the same user on the targeted host.

Rubeus attack with pass-the-ticket
Rubeus attack with pass-the-ticket

Let’s dissect this command line:

./Rubeus.exe s4u /user:DESKTOP-LOL42XPS$ /aes256:0572acc64a7cd6fd486768c58b8139462e4d6bd7c6cc5000959c16e5ae784b40 /domain:panda.lab /msdsspn:cifs/desktop-u2v0mfq.panda.lab /impersonateuser:administrator /ptt

At the time of writing, the Rubeus version used is the one from Shamir’s repository:

The “s4u” is the subcommand, or attack here, performed. It needs a controlled account, e.g. DESKTOP-LOL42XPS$. This account is the one with the SPN, the same one in the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute of the computer’s object.

The AES parameter is the Kerberos key associated to the account. It is used to build the TGS requests for both the S4U2Self and S4U2Proxy phases.

You can easily retrieve the key using the “sekurlsa::ekeys” command of Mimikatz on the compromised computer and look for the entry corresponding to the LocalSystem account (with the 999 authentication ID or the S-1-5-18 SID). Or you can use the “DCSync” feature and use the retrieved AES key.
Computer account entry
Computer account entry

The domain and impersonated user parameters are simply used to create a ticket for the said user for each TGS request.

And finally, the “ptt” parameter tells Rubeus to insert the retrieved ticket in the current session’s tickets cache, allowing the current user to use the ticket.

Using the ticket is as simple as mount C$
Using the ticket is as simple as mount C$

Now let’s examine the output of Rubeus. The first thing to have is a TGT so that the TGS request can be performed. This step basically proves to the KDC that you’re authenticated with the DESKTOP-LOL42XPS$ account. This also enables you to create a TGS request, in which you need the session key shared between you and the KDC, SC,K in the literature, and retrieved in the TGT request’s response.

The second operation is to ask for a TGS for the Administrator user on the current, controlled computer, here DESKTOP-LOL42XPS$. This is a S4U2Self operation and is at least used by Windows to check the effective rights on the filesystem. The TGS service thus dutifully answers and give us the requested, non-forwardable ticket.

The last Kerberos operation is to ask for a TGS for the same Administrator user, but on the targeted service and account, respectively CIFS and desktop-u2v0mfq here. This is a S4U2Proxy operation which performs a TGS request just like S4U2Self did, but with the previously obtained ticket added in the request (in the “additional-tickets” field). This additional ticket tells the TGS service on the Domain Controller not to use the requestor’s name in the to-be-created ticket’s client name, but instead use the additional ticket’s one.

Now here’s the interesting part: this should not be possible. At least, in the classical Kerberos delegation idea, using the “msDS-AllowedToDelegateTo” attribute, the TGS service will refuse to give an impersonated TGS when the included additional ticket is not marked as forwardable. And the ticket we gave is not marked as forwardable, because we get it from a S4U2Self operation.

However, as per the Microsoft specifications, the forwardable  flag is not checked when the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute is used. Quoting Shamir, it is a feature, not a bug. And so it works! We retrieve a TGS for the user Administrator on the requested service.

The last part to finish the attack is simply to use the retrieved ticket to authenticate on the targeted service, cifs/desktop-u2v0mfq.panda.lab.

Abusing resource-based constrained delegation in practice - Courtesy of Elad Shamir
Abusing resource-based constrained delegation in practice - Courtesy of Elad Shamir


Efficiently detect the attack in your environment
Detecting S4U2Self backdoors when you are not using Alsid’s solution

Not everybody has access to Alsid for AD product, but everything is not lost.

First of all, a small PowerShell script can be run on an ad hoc basis to retrieve all the ACEs specifically concerning the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute:

Import-Module ActiveDirectory

# First get the GUID (spoiler, it will be 3f78c3e5-f79a-46bd-a0b8-9d18116ddc79)
$rootDSE = Get-ADRootDSE
$scopedAttribute = "msDS-AllowedToActOnBehalfOfOtherIdentity"
$scopedSchemaIDGUID = (Get-ADObject -SearchBase $($rootDSE.schemaNamingContext) -LDAPFilter "(lDAPDisplayName=$scopedAttribute)" -Properties schemaIDGUID).schemaIDGUID

# Then for each AD object, look for an incriminating ACE
Get-ADObject -Filter * -Properties nTSecurityDescriptor | ForEach-Object {
    $adObject = $_
    $acls = $adObject.nTSecurityDescriptor.Access |
        Where-Object ObjectType -eq $scopedSchemaIDGUID |
        Where-Object {
        $_.AccessControlType -eq 'Allow' -and
        $_.ActiveDirectoryRights -eq 'WriteProperty' -and
        $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -ne 'S-1-5-10'

    if ($acls) {
            DistinguishedName = $adObject.DistinguishedName
            Access            = $acls



Its output is each object that has at least one ACE in its DACL that explicitly authorize the Write Property right on the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute for other users than “Self”.

A second script can be used to list every object having a non-empty “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute:

Get-ADObject -LDAPFilter "(msDS-AllowedToActOnBehalfOfOtherIdentity=*)" -Properties msDS-AllowedToActOnBehalfOfOtherIdentity | ForEach-Object {
        DistinguishedName                          = $_.DistinguishedName
        'msDS-AllowedToActOnBehalfOfOtherIdentity' = $_.'msDS-AllowedToActOnBehalfOfOtherIdentity'.Access.IdentityReference.Value


This script outputs the object’s DistinguishedName and the content of the attribute. Both scripts can be run with a user without any privilege, it just needs to be able to read the “nTSecurityDescriptor” and the “msDS-AllowedToActOnBehalfOfOtherIdentity” attributes.

Those commands do not monitor the AD in live, so you might be able to run them occasionally, but it might already be too late. What you need is to be alerted as soon as something like this appears on your AD. Without Alsid for AD, you can leverage the SACL mechanism on your AD to produce an event when a certain condition is met.

Import-Module ActiveDirectory

$rootDSE = Get-ADRootDSE

# Create a lDAPDisplayName -> schemaIDGUID mapping
$ldapDisplayNameToSchemaIdGuid = @{}
Get-ADObject -SearchBase $($rootDSE.schemaNamingContext) `
    -LDAPFilter "(schemaIDGUID=*)" `
    -Properties lDAPDisplayName, schemaIDGUID | ForEach-Object {
    $ldapDisplayNameToSchemaIdGuid[$_.lDAPDisplayName] = [GUID]$_.schemaIDGUID

# Object class, attribute and scope to configure auditing for
$scopedObject = "user"
$schemaIDGUIDScopedObject = $ldapDisplayNameToSchemaIdGuid[$scopedObject]
$scopedAttribute = "msDS-AllowedToActOnBehalfOfOtherIdentity"
$schemaIDGUIDScopedAttribute = $ldapDisplayNameToSchemaIdGuid[$scopedAttribute]
$inheritanceScope = "Descendents"

# Security principal to audit for actions: every user
$securityPrincipalObject = [Security.Principal.NTAccount]'Everyone'

# Define the entry
$rightsCollection = [System.DirectoryServices.ActiveDirectoryRights]::WriteProperty
$auditType = [System.Security.AccessControl.AuditFlags]::"Success", "Failure"
$auditDefinition = $securityPrincipalObject, $rightsCollection, $auditType, $schemaIDGUIDScopedAttribute, $inheritanceScope, $schemaIDGUIDScopedObject
$auditRule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule($auditDefinition)

# Get, add, update the ACL
$drivePath = "AD:\$($rootDSE.defaultNamingContext)"
$acl = Get-Acl $drivePath -Audit
$acl | Set-Acl $drivePath

This last script hopefully has to be launched from a privileged user, otherwise random users could update the rights of all of the AD objects.

The eventId 4742 is generated when the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute is modified. This is a generic event and this attribute isn’t listed, so you will not see the newly-set value nor will you be sure that this is the changed attribute, e.g. if you have other SACL generating this eventId:

AD Event log 4742
AD Event log 4742

Even though you will not be able to know for sure this is the attribute that has been changed, you can see the targeted computer in the “TargetUserName”/“TargetSid” and the writer of the attribute in the “SubjectUserName”/“SubjectUserSid”.

Alsid customers, you are already protected.

Throughout this attack, there are a few ways to alert a SOC.

The first thing Alsid for AD detects is an ACE allowing a security principal other than “Self” to write in the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute when it has already been present for a time, but also as soon as it is set, e.g. for persistence purposes. This is done by combining the review of the entire objects’ ACLs with an understanding of the replication process, enabling live monitoring of changes happening on the Directory.

Alsid for AD - Detecting dangerous ACE
Alsid for AD - Detecting dangerous ACE

In the same idea, having new users being added to the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute is not something done on a daily basis and Alsid for AD will raise alert about it as it sees all the changes made in the AD. Thus, it can send the attribute change to a SOC, which will be able to correlate this with other data to decide to raise an alert or not.

The security analysis is therefore entirely managed by Alsid, Customers do not have to configure anything specific and test the impact on their AD infrastructure, you merely need to review the results from the web interface and clear the attribute if not legit.

Clear the msDS-AllowedToActOnBehalfOfOtherIdentity attribute
Clear the msDS-AllowedToActOnBehalfOfOtherIdentity attribute

There already exist a lot of control possibilities between objects, all having their specificities, but Shamir found yet another way to control an object from another one. If an attacker can control an account with an SPN and can control the “msDS-AllowedToActOnBehalfOfOtherIdentity” on another one, then he can own the latter’s host server.

At Alsid, we track those control relationships between objects to provide you a top-notch AD security level. This kind of new control relationship has already been added to our Indicators-of-Exposure database, so sleep well tonight, dear Customers, because we have your back.

Romain Coltel
Senior Security Researcher
Former senior security auditor specialized in red-teaming missions, Romain is now tackling Active Directory problems down to the core at Alsid. During his spare time Romain is teaching the well-received SANS SEC660 in France and maintains various security software such as Dislocker or the AES-XEX and XTS modes for the famous mbedTLS library.


Découvrons ensemble comment Alsid peut améliorer la sécurité de vos infrastructures d’annuaire