The PowerView PowerUsage Series #4
This is a short follow-up to my âA Guide to Attacking Domain Trustsâ post, and the fourth post in my âPowerView PowerUsageâ series. It follows the same Scenario/Solution/Explanation pattern as the previous entries, with the original post containing a constantly updated list of the entire series.
One of the methods for trust hopping that I briefly covered in the trust post (under the âCase 3: Foreign ACL Principalsâ section) was the enumeration of DACL/ACE entries on domain objects where the principal (i.e. the user/group that holds the right over the specified object) is in a different domain than the target object. As mentioned, most of the ntSecurityDescriptor property of Active Directory objects is: (1) accessible to any domain authenticated user, and (2) replicated in the global catalog. This means that you can query the DACLs for all objects in a trusting domain from your current trusted domain context and filter any ACE entries where a foreign security principal has the given right on the object youâre enumerating.
The Scenario
You want to figure out what DACL/ACE entries in a specified domain contain principals NOT located in that specified domain. That is, you want to find inbound cross-domain security descriptor relationships for a target domain. For this example, weâll assume that weâre currently in testlab.local and are targeting dev.testlab.local.
The Solution
$Domain = "dev.testlab.local"
$DomainSid = Get-DomainSid $Domain
Get-DomainObjectAcl -Domain $Domain -ResolveGUIDs -LDAPFilter '(|(objectclass=groupPolicyContainer)(objectclass=group)(objectclass=user)(objectclass=domain))' | ? {
($_.AceType -match 'AccessAllowed') -and `
($_.SecurityIdentifier -match '^S-1-5-.*-[1-9]\d{3,}$') -and `
($_.SecurityIdentifier -notmatch $DomainSid) -and `
($_.ActiveDirectoryRights -match 'WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner')
} | % {
$_ | Add-Member Noteproperty 'PrincipalDN' $(Convert-ADName $_.SecurityIdentifier -OutputType DN)
$_
}
cross_trust_dacls.ps1Â
The Explanation
This snippet looks pretty similar to the one from the third post in this series. Before we do anything else, we grab the SID (security identifier) of the foreign domain with PowerViewâs Get-DomainSid. This allows us to filter out ACE entries where the SecurityIdentifier of the trustee/principal (the object that has the rights) is in the same domain as the enumerated object. This lets us later filter for these cross-trust ACE relationships.
To kick everything off, we use PowerViewâs Get-DomainObjectAcl to enumerate the ACEs for certain objects in a foreign domain, specified with -Domain âdev.testlab.localâ. Thereâs more data about how this works under the hood in the âData Enumeration Across Trusts With PowerViewâ section of my A Guide to Attacking Domain Trusts post. The -LDAPFilter differs from the third post, however. In this case we are searching for group policy, group, user, computer, and domain objects, i.e. objects we currently have takeover primitives for. Since computer objects also contain âuserâ in their objectclass, we donât need to explicitly specify âcomputerâ. Like the last snippet, the -ResolveGUIDs flag indicates that any target GUIDs in the ACEs should be resolved to their human-readable names.
We then implement a custom filter with ? {âĤ} (Where-Object), with lots of clauses:
- First, we check to make sure that the AceType specifies an ALLOW entry.
- Second, we again use the â^S-1â5-.*-[1â9]\d{3,}$â regex against the SecurityIdentifier to return only results where the security identifier of the trustee has a relative identifier (RID) of -1000 and above. This filters out principals that are built, reducing some of the noise.
- Third, we filter out principals from the same domain as the object by executing a negative regex match against the previously enumerated foreign domain SID.
- Finally, the last clause matches for rights in the ACE that indicate some type of control relationship (generic all rights, rights to change the owner, or other âobject takeoverâ primitive) that enables compromise of the target object. For more information on this type of relationship/attack, check out @_wald0âs and my âAn ACE Up the Sleeveâ whitepaper from Black Hat 2017.
Next, we process each ACE result on the pipeline by way of % {âĤ} (ForEach-Object). Instead of extracting out specific properties and creating a new object, like in the third post, we resolve the SecurityIdentifier of the ACE to a distinguished name by using PowerViewâs Convert-ADName with the -OutputType set to DN (distinguished name) and add this as a new property to the resulting ACE object returned on the pipeline.

Note:Â this will likely take a while to run, because weâre enumerating and parsing the security descriptor information for a large number of objects.
Originally published at harmj0y.