A tale of Active Directory delegation attacks
The intent of this post is only to record tools, techniques and concepts behind some Active Directory (AD) delegation attacks for personal use.
… So I can return to these shenanigans and refresh my memory in the future. ;)
1. Unconstrained Delegation
Overview
Unconstrained delegation first appeared on Windows Server 2k aiming to solve the “Kerberos double hop” problem. Considering that user wants to access a ServiceA that interacts with a ServiceB via Kerberos:
Figure 1: Uncontrained Delegation (shenaniganslabs.io)
- User performs the pre-auth (sending a timestamp encrypted with its NTLM hash) and receives a TGT from the KDC (AS-REQ and AS-REP, respectively).
- User sends the TGT back to the KDC, requesting access to ServiceA. (TGS-REQ).
- KDC recognizes that the computer behind ServiceA has Unconstrained Delegation enabled - that is, it has the attribute TrustedForDelegation = true. It will then return a packet containing ((TGS for ServiceA) + (TGT for User)) to User.
- When connecting to ServiceA, User sends the TGS + TGT received in step 4. ServiceA stores User’s TGT in its LSASS in order to impersonate it when accessing ServiceB (delegation).
- If User needs information from ServiceB, ServiceA will request the KDC using User’s TGT for a TGS for ServiceB.
- The KDC then returns to ServiceA a valid TGS for ServiceB.
- ServiceA requests directly to ServiceB using this TGS and returns the information received to User.
Enumeration
Finding computers/users with unconstrained delegation:
- AD Module
- Powerview
Exploitation
- Mimikatz
Inside a computer with unconstrained delegation, check tickets in memory:
Nothing interest? Coerce someone to connect to this box. Some options:
- mitm6
- printerbug (spoolsample)
- responder
Check with “Invoke-UserHunter” for new connections on the server:
Once you get the TGT ticket… extract and inject it to memory using mimikatz:
- Rubeus
Monitor new TGT tickets on memory with Rubeus monitor:
After getting a privileged TGT… just copy the base64 string and paste on this way:
Check klist and enjoy. o/
2. Constrained Delegation
Overview
Unlike Unconstrained Delegation, where it would be possible to delegate privileges to any computer, the basic principle behind Constrained Delegation is that a service can only delegate privileges for specific SPNs (e.g., CIFS/computerA.lab.local).
A typical scenario where Constrained Delegation is applied: Users need to connect to a service, but without using Kerberos authentication (using other ways to authenticate, such as NTLM or even form-based authentication). For this scenario, AD created extensions that would allow the first hop service to impersonate users: Service for User to Self (S4U2self) and Service for User to Proxy (S4U2Proxy).
Figure 2: Constrained Delegation (docs.microsoft.com)
- User1 makes a request to Service1. The user is authenticated, but Service1 does not have the user’s authorization data. Typically this is due to the authentication being performed by some means other than Kerberos (form-based or NTLM).
- Service1, which has already authenticated with the KDC and has obtained its TGT (AS-REQ + AS-REP), asks for a TGS to itself (also called “forwardable TGS”) on behalf of the named user by using the S4U2self extension (User1 is identified on S4U2self simply by its username and realm name - opportunity to impersonate!).
- The KDC returns a forwardable TGS addressed to Service1 as if it had been requested from the user with the user’s own TGT. The service ticket might contain the authorization data of the user (what he can/cannot access in Service1).
- Service 1 can use the authorization data from the service ticket to fulfill the user’s request. The service then responds to the user.
- User1 makes then a request to Service1. Service1 needs to access resources on Service2 as the user (delegation). However, Service1 does not have a forwarded TGT from the user to perform delegation by a forwarded TGT, as described before for Unconstrained Delegation. Thus, two preconditions need to be met by service1 so that it can delegate User1 privileges to Service2:
- Have a valid TGT. (That is, having already authenticated to Kerberos - AS-REQ + AS-REP)
- Have a forwardable TGS, that is, a TGS to itself on behalf of User1. Service1 must always present the forwardable TGS obtained in the previous step (via S42Uself) for the S4UProxy extension as a proof that the user, who is being impersonated by Service1, has already authenticated himself in Service1 before.
- If Service1 meets these two preconditions, it can request a TGS for Service2 on the KDC via the S4U2Proxy extension. Service1 then requests to the KDC a TGS to Service2 on behalf of User1 via S42UProxy extension. Again, User1 is identified by its name and realm contained in the forwardable TGS for Service1 (step 2 and 3).
- KDC returns a “TGS for Service 2” to Service 1, but the client identity stored in the cname and crealm fields of the TGS are that of the User1, not Service 1.
- Finally, Service1 uses the service ticket to make a request to Service2. Service2 treats this request as coming from the user and assumes that the user was authenticated by the KDC.
- Service2 responds to the request.
- Service1 responds to the User1 request.
Enumeration
Finding computers/users with constrained delegation:
Exploitation
Ask a TGT to impersonate the user allowed to delegate privileges (lab.local\sqlservice) and then request a s4u (s4u2self + s4u2proxy) on behalf of a high privileged user (lab.local\Administrator).
- Rubeus
As sqlservice has “CIFS/DC01LAB.lab.local” set on your msDS-AllowedToDelegateTo property, it would be possible to consider another service available for this same computer, such as ldap (in a DC, it would allow DCSync). The /altservice parameter do the work!
Or all-in-one command:
- Kekeo + Mimikatz
Use mimikatz to inject this ticket in-memory:
Check with klist to verify that everything went well.
- Impacket
Having access to CIFS… we can dump SAM database.
3. Resource-Based Constrained Delegation (RBCD)
Overview
- Feature that initially appeared in Windows Server 2012, as a new method for “delegation”, based on constrained delegation.
- It is very similar to the classic constrained delegation but works in the opposite direction. @elad_shamir did a brilliant and detailed post about RBCD on his blog: Wagging the Dog.
- Classic constrained delegation from serviceA to serviceB is configured on serviceA in the “msDS-AllowedToDelegateTo” attribute, and defines an “outgoing” trust from serviceA to serviceB, while resource-based constrained delegation is configured on serviceB in the “msDS-AllowedToActOnBehalfOfOtherIdentity” attribute, and defines an “incoming” trust from serviceA to serviceB.
- A key point, and demonstrated by @elad_shamir in his blogspot, is that the UserAccountControl flag “TrustedToAuthForDelegation” is not really required to perform S4U2Self. What actually happens is that if a user who does not have “TrustedToAuthForDelegation” performs S4U2Self, a non-forwardable TGS will be returned.
- A non-forwardable TGS would not be valid for S4U2Proxy in a classic constrained delegation, but it would be valid for Resource-Based Constrained Delegation.
- Thus, if we have DACL rights for a computer (e.g., GenericAll) and a user with SPN set, it would be possible to achieve a “computer takeover” via RBCD. As every regular user in AD has privileges to create up to 10 computer accounts, it would be easy to get an account with SPN. The Powermad tool could be used for this.
- The generic abuse case would work as follows (from @elad_shamir blogpost):
Figure 3: RBCD Abuse (shenaniganslabs.io)
- The attacker compromises an account that has an SPN or creates one (“Service A”) and the DACL to configure resource-based constrained delegation on a computer account (“Service B”).
- The attacker configures resource-based constrained delegation from Service A to Service B.
- The attacker uses Rubeus to perform a full S4U attack (S4U2Self and S4U2Proxy) from Service A to Service B for a user with privileged access to Service B (e.g., Domain\Administrator).
- The attacker can pass-the-ticket and impersonate the user to gain access to Service B.
Enumeration
In most exploitation scenarios involving RBCD, we are interested in AD objects that have write privileges to a computer (e.g., GenericWrite, GenericAll, WriteDACL).
Assuming that we have already compromised an AD user account “UserA”, PowerView could be used to check the privileges of this user against an arbitrary computer account “ComputerA”:
If the “ActiveDirectoryRights” returned from “Get-DomainObjectAcl” command indicates GenericWrite/GenericAll/WriteDACL, it would be possible to compromise this computer via RBCD.
Exploitation
Source: https://gist.github.com/HarmJ0y/224dbfef83febdaf885a8451e40d52ff (@harmj0y)