Domain trusts
Trust Table Side By Side
Shared, 1 to many
Direct trust
The trust is shared with anyone in the forest
Not extended to next level child domains
Forest, tree-root, parent-child, and cross-link trusts are transitive
Typical for external or custom trust setups
Parent-child
: Two or more domains within the same forest. The child domain has a two-way transitive trust with the parent domain, meaning that users in the child domaincorp.inlanefreight.local
could authenticate into the parent domaininlanefreight.local
, and vice-versa.Cross-link
: A trust between child domains to speed up authentication.External
: A non-transitive trust between two separate domains in separate forests which are not already joined by a forest trust. This type of trust utilizes SID filtering or filters out authentication requests (by SID) not from the trusted domain.Tree-root
: A two-way transitive trust between a forest root domain and a new tree root domain. They are created by design when you set up a new tree root domain within a forest.Forest
: A transitive trust between two forest root domains.ESAE: A bastion forest used to manage Active Directory.
Trusts can be set up in two directions: one-way or two-way (bidirectional).
One-way trust
: Users in atrusted
domain can access resources in a trusting domain, not vice-versa.Bidirectional trust
: Users from both trusting domains can access resources in the other domain. For example, in a bidirectional trust betweenINLANEFREIGHT.LOCAL
andFREIGHTLOGISTICS.LOCAL
, users inINLANEFREIGHT.LOCAL
would be able to access resources inFREIGHTLOGISTICS.LOCAL
, and vice-versa.
Enumerating Trust Relationships
Using Get-ADTrust (built-in)
The above output shows that our current domain INLANEFREIGHT.LOCAL
has two domain trusts. The first is with LOGISTICS.INLANEFREIGHT.LOCAL
, and the IntraForest
property shows that this is a child domain, and we are currently positioned in the root domain of the forest. The second trust is with the domain FREIGHTLOGISTICS.LOCAL,
and the ForestTransitive
property is set to True
, which means that this is a forest trust or external trust.
Checking for Existing Trusts using Get-DomainTrust (PowerView)
PowerView can be used to perform a domain trust mapping and provide information such as the type of trust (parent/child, external, forest) and the direction of the trust (one-way or bidirectional).
Using Get-DomainTrustMapping
From here, we could begin performing enumeration across the trusts. For example, we could look at all users in the child domain:
Checking Users in the Child Domain using Get-DomainUser
Another tool we can use to get Domain Trust is netdom
. The netdom query
sub-command of the netdom
command-line tool in Windows can retrieve information about the domain, including a list of workstations, servers, and domain trusts.
Using netdom to query domain trust
Using netdom to query domain controllers
Using netdom to query workstations and servers
We can also use BloodHound to visualize these trust relationships by using the Map Domain Trusts
pre-built query. Here we can easily see that two bidirectional trusts exist.
Visualizing Trust Relationships in BloodHound
Attacking Domain Trusts - Child -> Parent Trusts - from Windows
SID History Primer
The sidHistory attribute is used in migration scenarios.
SID history is intended to work across domains, but can work in the same domain. Using Mimikatz, an attacker can perform SID history injection and add an administrator account to the SID History attribute of an account they control. When logging in with this account, all of the SIDs associated with the account are added to the user's token.
This token is used to determine what resources the account can access. If the SID of a Domain Admin account is added to the SID History attribute of this account, then this account will be able to perform DCSync and create a Golden Ticket or a Kerberos ticket-granting ticket (TGT), which will allow for us to authenticate as any account in the domain of our choosing for further persistence.
ExtraSids Attack - Mimikatz
This attack allows for the compromise of a parent domain once the child domain has been compromised. Within the same AD forest, the sidHistory property is respected due to a lack of SID Filtering protection. SID Filtering is a protection put in place to filter out authentication requests from a domain in another forest across a trust.
To perform this attack after compromising a child domain, we need the following:
The KRBTGT hash for the child domain
The SID for the child domain
The name of a target user in the child domain (does not need to exist!)
The FQDN of the child domain.
The SID of the Enterprise Admins group of the root domain.
With this data collected, the attack can be performed with Mimikatz.
First, we need to obtain the NT hash for the KRBTGT account, which is a service account for the Key Distribution Center (KDC) in Active Directory.
Since we have compromised the child domain, we can log in as a Domain Admin or similar and perform the DCSync attack to obtain the NT hash for the KRBTGT account.
Obtaining the KRBTGT Account's NT Hash using Mimikatz
We can use the PowerView Get-DomainSID
function to get the SID for the child domain, but this is also visible in the Mimikatz output above.
Using Get-DomainSID
Next, we can use Get-DomainGroup
from PowerView to obtain the SID for the Enterprise Admins group in the parent domain.
We could also do this with the Get-ADGroup cmdlet with a command such as Get-ADGroup -Identity "Enterprise Admins" -Server "INLANEFREIGHT.LOCAL"
.
Obtaining Enterprise Admins Group's SID using Get-DomainGroup
At this point, we have gathered the following data points:
The KRBTGT hash for the child domain:
9d765b482771505cbe97411065964d5f
The SID for the child domain:
S-1-5-21-2806153819-209893948-922872689
The name of a target user in the child domain (does not need to exist to create our Golden Ticket!): We'll choose a fake user:
hacker
The FQDN of the child domain:
LOGISTICS.INLANEFREIGHT.LOCAL
The SID of the Enterprise Admins group of the root domain:
S-1-5-21-3842939050-3880317879-2865463114-519
Before the attack, we can confirm no access to the file system of the DC in the parent domain.
Using ls to Confirm No Access
Using Mimikatz and the data listed above, we can create a Golden Ticket to access all resources within the parent domain.
Creating a Golden Ticket with Mimikatz
We can confirm that the Kerberos ticket for the non-existent hacker user is residing in memory.
Confirming a Kerberos Ticket is in Memory Using klist
From here, it is possible to access any resources within the parent domain, and we could compromise the parent domain in several ways.
Listing the Entire C: Drive of the Domain Controller
ExtraSids Attack - Rubeus
We can also perform this attack using Rubeus. First, again, we'll confirm that we cannot access the parent domain Domain Controller's file system.
Next, we will formulate our Rubeus command using the data we retrieved above. The /rc4
flag is the NT hash for the KRBTGT account. The /sids
flag will tell Rubeus to create our Golden Ticket giving us the same rights as members of the Enterprise Admins group in the parent domain.
Creating a Golden Ticket using Rubeus
Once again, we can check that the ticket is in memory using the klist
command.
Confirming the Ticket is in Memory Using klist
Finally, we can test this access by performing a DCSync attack against the parent domain, targeting the lab_adm
Domain Admin user.
When dealing with multiple domains and our target domain is not the same as the user's domain, we will need to specify the exact domain to perform the DCSync operation on the particular domain controller. The command for this would look like the following:
Attacking Domain Trusts - Child -> Parent Trusts - from Linux
We can also perform the attack shown in the previous section from a Linux attack host. To do so, we'll still need to gather the same bits of information:
The KRBTGT hash for the child domain
The SID for the child domain
The name of a target user in the child domain (does not need to exist!)
The FQDN of the child domain
The SID of the Enterprise Admins group of the root domain
Once we have complete control of the child domain, LOGISTICS.INLANEFREIGHT.LOCAL
, we can use secretsdump.py
to DCSync and grab the NTLM hash for the KRBTGT account.
Performing DCSync with secretsdump.py
Next, we can use lookupsid.py from the Impacket toolkit to perform SID brute forcing to find the SID of the child domain.
In this command, whatever we specify for the IP address (the IP of the domain controller in the child domain) will become the target domain for a SID lookup. The tool will give us back the SID for the domain and the RIDs for each user and group that could be used to create their SID in the format DOMAIN_SID-RID
. For example, from the output below, we can see that the SID of the lab_adm
user would be S-1-5-21-2806153819-209893948-922872689-1001
.
Performing SID Brute Forcing using lookupsid.py
Next, we can rerun the command, targeting the INLANEFREIGHT Domain Controller (DC01) at 172.16.5.5 and grab the domain SID S-1-5-21-3842939050-3880317879-2865463114
and attach the RID of the Enterprise Admins group. Here is a handy list of well-known SIDs.
Grabbing the Domain SID & Attaching to Enterprise Admin's RID
Next, we can use ticketer.py from the Impacket toolkit to construct a Golden Ticket. This ticket will be valid to access resources in the child domain (specified by -domain-sid
) and the parent domain (specified by -extra-sid
).
Constructing a Golden Ticket using ticketer.py
The ticket will be saved down to our system as a credential cache (ccache) file, which is a file used to hold Kerberos credentials. Setting the KRB5CCNAME
environment variable tells the system to use this file for Kerberos authentication attempts.
Setting the KRB5CCNAME Environment Variable
We can check if we can successfully authenticate to the parent domain's Domain Controller using Impacket's version of Psexec. If successful, we will be dropped into a SYSTEM shell on the target Domain Controller.
Impacket also has the tool raiseChild.py, which will automate escalating from child to parent domain. We need to specify the target domain controller and credentials for an administrative user in the child domain.
the script will do the rest. If we walk through the output, we see that it starts by listing out the child and parent domain's fully qualified domain names (FQDN). It then:
Obtains the SID for the Enterprise Admins group of the parent domain
Retrieves the hash for the KRBTGT account in the child domain
Creates a Golden Ticket
Logs into the parent domain
Retrieves credentials for the Administrator account in the parent domain
Finally, if the target-exec
switch is specified, it authenticates to the parent domain's Domain Controller via Psexec.
Performing the Attack with raiseChild.py
In a client production environment, we should always
be careful when running any sort of "autopwn" script like this, and always remain cautious and construct commands manually when possible.
We don't want to tell the client that something broke because we used an "autopwn" script!
Last updated