[Edit 8/13/15] – Here is how the old version 1.9 cmdlets in this post translate to PowerView 2.0:
- Invoke-FindUserTrustGroups -> Find-ForeignUser
- Invoke-FindAllUserTrustGroups -> Find-ForeignUser -Recurse
- Invoke-FindGroupTrustUsers -> Find-ForeignGroup
- Invoke-MapDomainTrusts -> Invoke-MapDomainTrust
- Get-NetDomainControllers -> Get-NetDomainController
- Invoke-EnumerateLocalAdmins -> Invoke-EnumerateLocalAdmin
- Invoke-EnumerateLocalTrustGroups -> Invoke-EnumerateLocalAdmin -TrustGroups
A few months ago, my colleague @sixdub and I presented our talk “Trusts You Might Have Missed” at BSides Chicago (the slides are posted here). We covered a lot of information that we’ve talked about in the “Trusts You Might Have Missed”, “Nodal Analysis of Domain Trusts – Maximizing the Win!”, and the “Domain Trusts: Why You Should Care” posts, as well as a few new developments. I wanted to do a writeup on the new material for anyone interested.
Enumerating and abusing Active Directory domain trusts is all about uncovering a potential mesh of hidden accesses that admins have set up previously (and often incorrectly). If a trust exists, the key is to try to figure out exactly what users have access to what resources across domains, and strategically compromise accounts that can help you achieve your goal. These new PowerView features can help you tease out the exactly nature of this access mesh.
New PowerView Features
I’ve mentioned PowerView‘s Invoke-FindUserTrustGroups cmdlet before. This will query a specific domain for all users, extract the group membership for each, and check if any users are in a group outside of the queried domain. This can help you figure out the nature of access for a domain’s outgoing trust access. That is, this function can help you figure out what users in your target (or current) domain have access to in another domain. This is really useful to run in a domain that you currently have access in (or have compromised) to help you figure out what else you might be able to jump to.
There’s also Invoke-FindAllUserTrustGroups, which will recursively map all reachable domain trusts (à la Invoke-MapDomainTrusts) and run Invoke-FindUserTrustGroups on each resulting domain in the trust mesh it can reach.
PowerView now also has the Invoke-FindGroupTrustUsers cmdlet. This function performs the reciprocal action, querying a domain for all groups, extracting the user membership for each, and checking if any users are outside of the queried domain. This can help you decipher the nature of a domain’s incoming trust access by showing you what users in other domains have access into your target (or current) domain:
This is really useful to run on a domain you’re targeting so you can decipher how it might be possible to hop into your target domain. The version that runs these actions on each reachable domain is Invoke-FindAllGroupTrustUsers.
One tactic we’ve used before as well is Get-NetDomainControllers -Domain <domain> | Get-NetLocalGroup. This will enumerate users who have local administrator privileges on all domain controllers in a target domain. We’ve often found domain trust groups added to the BUILTIN\Administrators group on domain controllers in networks, which can allow for cross-domain compromise. We’ve also used Invoke-EnumerateLocalAdmins function as well, which will enumerate the members of the Administrators localgroup for all machines in a domain. There’s more information about the workings of these methods in the “Pass-the-Hash is Dead: Long Live Pass-the-Hash” post.
We’ve now taken this one step further and combined these approaches, resulting in the Invoke-EnumerateLocalTrustGroups cmdlet. This function operates similarly to Invoke-EnumerateLocalAdmins, but only returns results that are not members of the target machine or machine’s domain, OR domain groups that have a user outside of the machine’s domain. This will take a while in a large network, but it will provide you with a really nice picture of what users have access to a domain’s resources across a trust.
Taken together, Get-NetDomainTrusts, Invoke-FindUserTrustGroups, Invoke-FindGroupTrustUsers, and Invoke-EnumerateLocalTrustGroups can give you an excellent account of the nature of a domain’s trust relationships.
Trust Keys
About a month ago, Benjamin Delpy (@gentilkiwi) dropped the following tweet:
I have to admit, I didn’t really grasp this tweet when I first read it. After doing a bit more research and speaking with Sean Metcalf (@pyrotek3, who also has a post on this topic as well), I think I can explain the implications of what Delpy released. But first, a bit on how kerberos authentication works with domain trusts.
Domain Trusts and Kerberos Authentication
In order for authentication to occur across a domain trust, the kerberos key distribution centers (KDCs) in two domains must have a shared secret, called an inter-realm key. This key is derived from a shared password, and rotates approximately every 30 days. Parent-child domains share an inter-realm key implicitly.
When a user in domain A tries to authenticate or access a resource in domain B that he has established access to, he presents his ticket-granting-ticket (TGT) and request for a service ticket to the KDC for domain A. The KDC for A determines that the resource is not in its realm, and issues the user a referral ticket.
This referral ticket is a ticket-granting-ticket (TGT) encrypted with the inter-realm key shared by domain A and B. The user presents this referral ticket to the KDC for domain B, which decrypts it with the inter-realm key, checks if the user in the ticket has access to the requested resource, and issues a service ticket. This process is described in detail in Microsoft’s documentation in the Simple Cross-Realm Authentication and Examples section.
Trust Keys and Mimikatz: A Golden Trust Ticket?
Mimikatz can now extract the inter-realm trust keys from domain controllers and forge referral TGTs, as shown in Delpy’s tweet. These tickets can then be presented directly to the target domain to get service tickets for resources the user in the referral ticket has access to. Since we can forge the contents of these referral tickets, this means that we can build them for any user in domain A that has access to resources in domain B, and take advantage of all the trust relationships enumerated by PowerView.
The natural question to ask now is “So what? If you’re in a position to extract these trust keys from a domain controller, you can also extract the krbtgt hash and build a golden ticket for any of these users. So why go about this route?”
Some organizations have begun to roll their krbtgt hash as a protection against golden ticket attacks. Microsoft even offers scripts to facilitate this process. However, if the krbtgt hash rolls, the trust keys will remain the same, allowing for the continued exploitation of trust access with these forged referral tickets.
If we’re talking about a large forest of parent-child domains, and an attacker compromises a domain controller in the forest root, it gets worse. All child domains in a forest have an implicit two-way transitive trust with their parent, and the Enterprise Admins group is automatically added to the local Administrators group for all machines in the forest. If an attacker can comprise a forest root DC and extract all of the trust keys, they can forge a referral ticket for an Enterprise Admin user and compromise all child domains in the forest. Again, this should work even if the krbtgt hash is changed for all domains.
Major props to Benjamin for adding these features into Mimikatz, and a big thanks again to Sean Metcalf for answering my pestering questions on this topic. And again, check out Sean’s post on this topic for a more in-depth dive, as well as some practical examples.