{
	"id": "ef88a4b3-2aea-4d9c-846b-0b6d3b28fbb1",
	"created_at": "2026-04-06T00:22:28.489885Z",
	"updated_at": "2026-04-10T03:21:53.570814Z",
	"deleted_at": null,
	"sha1_hash": "a9f884ecc28345e66e289e8895bc641365e092a4",
	"title": "A Guide to Attacking Domain Trusts",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 7964447,
	"plain_text": "A Guide to Attacking Domain Trusts\r\nBy Will Schroeder\r\nPublished: 2017-10-30 · Archived: 2026-04-05 22:02:13 UTC\r\nIt’s been a while (nearly 2 years) since I wrote a post purely on Active Directory domain trusts. After diving into\r\ngroup scoping, I realized a few subtle misconceptions I previously had concerning trusts and group memberships.\r\nThat, combined with the changes made to PowerView last year, convinced me to publish an up-to-date guide on\r\nenumerating and attacking domain trusts. This will likely be the last post focusing on domain trusts I publish for a\r\nwhile, and at over 8000 words, it’s not exactly a light read (not that anyone reads long posts 😉 In general, I don’t\r\njust blog my operational notes — I try to write posts that function as complete guides for members of my team,\r\nwith the hope that the information may be of use to others (whether from an offensive or defensive perspective.)\r\nI want this to be as complete as possible, so I’ll cover every aspect of trusts as we currently understand them. Just\r\nas with my previous posts, I want to encapsulate my knowledge of the topic as best I can at this point in time.\r\nEmphasis on “this point in time.” Our knowledge and tradecraft are always evolving, and trusts are no different. I\r\nhad a number of fuzzy misconceptions regarding domain trusts when I started writing about them. I was never a\r\nsysadmin or AD architect — I’ve learned my knowledge piecemeal, which (hopefully) explains the gaps that have\r\nsurfaced in my past posts, and the ones that I’m sure will continue to arise.\r\nSo I am going to start fresh, in case you are not familiar with the previous posts I pushed out about trusts. As such,\r\na few parts of this post will recycle certain elements and wording from previous work, integrated with updated\r\nknowledge and PowerView syntax. And as this is a bit of a tome of an article, I’m sure there as mistakes\r\nsomewhere and things that I’ve missed, so when you find them let me know and I’ll update appropriately!\r\nPowerView’s most up-to-date version will always be on the dev branch of PowerSploit.\r\nWTF Are Domain Trusts?\r\nAt a high level, a domain trust establishes the ability for users in one domain to authenticate to resources or act\r\nas a security principal in another domain. Microsoft has a lot of information out there about domain trusts, as well\r\nas “Security Considerations for Trusts”, and it can sometimes get a bit confusing. As Microsoft describes, “Most\r\norganizations that have more than one domain have a legitimate need for users to access shared resources located\r\nin a different domain“, and trusts allow organizations with multiple domains to grant users in separate domains\r\naccess to shared resources. Domain forests are collections of domain containers that trust each other. Forests\r\nthemselves may also have trusts between them. Microsoft has excellent post about how domain and forest trusts\r\nwork. If you’re not familiar with this topic, I recommend that you check it out.\r\nEssentially, all a trust does is link up the authentication systems of two domains and allows authentication traffic\r\nto flow between them through a system of referrals. If a user requests access to a service principal name (SPN) of\r\na resource that resides outside of the domain they’re current in, their domain controller will return a special\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 1 of 35\n\nreferral ticket that points to the key distribution center (KDC, in the Windows case the domain controller) of the\r\nforeign domain.\r\nThe user’s ticket-granting-ticket (TGT) is included in this TGS-REP (ticket-granting service reply) referral ticket,\r\nand this ticket encrypted/signed with the inter-realm trust key that the domains previously exchanged, instead of\r\nthe first domain’s krbtgt account. This ticket is usually referred to as an “inter-realm ticket-granting-ticket/TGT.”\r\nThe foreign domain then verifies/decrypts the TGT included in the referral by decrypting it with the previously\r\nnegotiated inter-realm trust key, and goes about the rest of the normal Kerberos process.\r\nSean Metcalf has a great breakdown of this process in his “It’s All About Trust” post, and he describes the process\r\nas, “Once there is a trust between two domains … the ticket-granting service of each domain (“realm” in\r\nKerberos speak) is registered as a security principal with the other domain’s Kerberos service (KDC). This\r\nenables the ticket-granting service in each domain to treat the one in the other domain as just another service\r\nproviding cross-domain service access for resources in the other domain.”\r\nSo basically, when the foreign domain decrypts the referral ticket with the negotiated trust key, it sees the user’s\r\nTGT and says “OK, the other domain already authenticated this user and said this is who they say they are/these\r\nare the groups the user is in, so I’ll trust this information as accurate because I trust the domain that issued the\r\nreferral.”\r\nHere’s a picture to visualize the Kerberos process across trust boundaries:\r\nThe purpose of establishing a trust is to allow users from one domain to access resources (like the local\r\nAdministrators group on a server), to be nested in groups, or to otherwise be used as security principals in another\r\ndomain (e.g. for AD object ACLs). One exception to this is intra-forest trusts (domain trusts that exist within the\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 2 of 35\n\nsame Active Directory forest)- any domain created within a forest retains an implicit two-way, transitive trust\r\nrelationship with every other domain in the forest. This has numerous implications which will be covered later in\r\nthis post.\r\nBut before that, we have to cover a few more characteristics of trusts.\r\nThere are several types of trusts, some of which have various offensive implications, covered in a bit:\r\nParent/Child — part of the same forest — a child domain retains an implicit two-way transitive trust with\r\nits parent. This is probably the most common type of trust that you’ll encounter.\r\nCross-link — aka a “shortcut trust” between child domains to improve referral times. Normally referrals in\r\na complex forest have to filter up to the forest root and then back down to the target domain, so for a\r\ngeographically spread out scenario, cross-links can make sense to cut down on authentication times.\r\nExternal — an implicitly non-transitive trust created between disparate domains. “External trusts provide\r\naccess to resources in a domain outside of the forest that is not already joined by a forest trust.” External\r\ntrusts enforce SID filtering, a security protection covered later in this post.\r\nTree-root — an implicit two-way transitive trust between the forest root domain and the new tree root\r\nyou’re adding. I haven’t encountered tree-root trusts too often, but from the Microsoft documentation,\r\nthey’re created when you when you create a new domain tree in a forest. These are intra-forest trusts, and\r\nthey preserve two-way transitivity while allowing the tree to have a separate domain name (instead of\r\nchild.parent.com).\r\nForest — a transitive trust between one forest root domain and another forest root domain. Forest trusts\r\nalso enforce SID filtering.\r\nMIT — a trust with a non-Windows RFC4120-compliant Kerberos domain. I hope to dive more into MIT\r\ntrusts in the future.\r\nTransitivity, huh? Another aspect of domain trusts is that they are transitive or non-transitive. To quote the MSDN\r\ndocumentation on transitivity: “A transitive trust extends trust relationships to other domains; a nontransitive\r\ntrust does not extend trust relationships to other domains.” This means that transitive trusts can be chained, so\r\nusers can potentially access resources in multiple domains. Meaning, if domain A trusts B, and B trusts C, then A\r\nimplicitly trusts C. Under the hood, if a specific trust relationship is transitive, then the trusting domain can repack\r\na user’s TGT into additional referral tickets and forward them onto domains that domain trusts.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 3 of 35\n\nAlso, trusts can be one-way or two-way. A bidirectional (two-way) trust is actually just two one-way trusts. A one-way trust means users and computers in a trusted domain can potentially access resources in another trusting\r\ndomain. A one-way trust is in one direction only, hence the name. Users and computers in the trusting domain can\r\nnot access resources in the trusted domain. Microsoft has a nice diagram to visualize this:\r\nhttps://technet.microsoft.com/en-us/library/cc759554(v=ws.10).aspx\r\nThis was something that messed with my head when I started — from an offensive perspective, what we care\r\nabout is the direction of access, not the direction of the trust. With a one-way trust where A -trusts-\u003e B, if the trust\r\nis enumerated from A, the trust is marked as outbound, while if the same trust is enumerated from B the trust is\r\nmarked as inbound, while the potential access is from B to A. This will make more sense in the Foreign\r\nRelationship Enumeration section.\r\nWhy Care?\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 4 of 35\n\nBut really, why care?\r\nDomain trusts often introduce unintended access paths between environments. In many organizations, trusts were\r\nimplemented years (sometimes 10+) ago without major considerations given to security. Some corporate entities\r\nthat are focused on acquisitions often just “plug in” a new company’s Active Directory network either as a child\r\ndomain or external trust, without fully considering the security implications.\r\nBecause historically there have not been many toolsets that allow you to easily map, enumerate, and visualize the\r\nrisk associated with misconfigured trusts, many domain architects are unaware of the unintentional risk exposed\r\nby their Active Directory trust architectures. This links back to the idea of “misconfiguration debt”\r\nthat @wald0, @cptjesus, and I spoke about at Derbycon this year. Because of this, various red teams (and\r\nprobably APTz, I’m assuming) have been abusing Active Directory trusts for years with great success.\r\nA common scenario is compromising a development or subsidiary domain and leveraging that access to pivot into\r\nthe secure root/enclave. This also introduces opportunities for persistence- why leave code running in a secured\r\nenvironment, when you can have implants running in the less-secured (but trusted) domain that can then be used\r\nto re-compromise your target at will?\r\nAn intra-forest trust (parent/child or tree-root) introduces an awesome attack vector that’s described in The\r\nTrustpocalypse later in this post. External/inter-forest trusts do not guarantee any kind of privileged access, but at\r\na minimum, a trust means that you can query any normal Active Directory information from a domain that trusts\r\nyou (yes, this means in some cases you can Kerberoast across trusts, more on this at the end of post.) After all,\r\nActive Directory is meant as a queryable database of information, and trusts don’t change that!\r\nA Trust Attack Strategy\r\nBefore we get into the technical details of how to enumerate and abuse trusts, I wanted to go over the high level\r\nstrategy I use when auditing trust relationships. When I talk about a “trust attack strategy” what I mean is a way to\r\nlaterally move from the domain in which your access currently resides into another domain you’re targeting.\r\n(1) The first step is to enumerate all trusts your current domain has, along with any trusts those domains have, and\r\nso on. Basically, you want to produce a mapping of all the domains you can reach from your current context\r\nthrough the linking of trust referrals. This will allow you to determine the domains you need to hop through to get\r\nto your target and what techniques you can execute to (possibly) achieve this. Any domains in the mapped “mesh”\r\nthat are in the same forest (e.g. parent-\u003echild relationships) are of particular interest due to the SIDhistory-trust-hopping technique developed by Sean Metcalf and Benjamin Delpy, also covered in the The\r\nTrustpocalypse section.\r\n(2) The next step is to enumerate any users/groups/computers (security principals) in one domain that either (1)\r\nhave access to resources in another domain (i.e. membership in local administrator groups, or DACL ACE\r\nentries), or (2) are in groups or (if a group) have users from another domain. The point here is to find relationships\r\nthat cross the mapped trust boundaries in some way, and therefore might provide a type of “access bridge” from\r\none domain to another in the mesh. While a cross-domain nested relationship is not guaranteed to facilitate access,\r\ntrusts are normally implemented for a reason, meaning more often than not some type of cross-domain\r\nuser/group/resource “nesting” probably exists, and in many organizations these relationships are misconfigured.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 5 of 35\n\nAnother subnote- as mentioned, Kerberoasting across trusts may be another vector to hop a trust boundary. Check\r\nout the Another Sidenote: Kerberoasting Across Domain Trusts section for more information.\r\n(3) Now that you have mapped out the trust mesh, types, and cross-domain nested relationships, you have a map\r\nof what accounts you need to compromise to pivot from your current domain into your target. By performing\r\ntargeted account compromise, and utilizing SID-history-hopping for domain trusts within a forest, we have been\r\nable to pivot through up to 7+ domains in the field to reach our objective.\r\nAt a minimum, remember that if a domain trusts you, i.e. if the trust is bidirectional or if one-way and inbound,\r\nthen you can query any Active Directory information from the trusting domain. And remember that all parent-\r\n\u003echild (intra-forest domain trusts) retain an implicit two way transitive trust with each other. Also, due to how\r\nchild domains are added, the “Enterprise Admins” group is automatically added to Administrators domain local\r\ngroup in each domain in the forest. This means that trust “flows down” from the forest root, making it our\r\nobjective to move from child to forest root at any appropriate step in the attack chain.\r\nOK, How Do I Enumerate Trusts?\r\nOK Will, you’ve piqued my interest. How do I go about figuring out what trust relationships exist in my\r\nenvironment?\r\nAs far as I know, there are three main methods to enumerate trusts: Win32 API calls, various .NET methods, and\r\nLDAP. Each one (frustratingly) returns a differing set of information, and each one has different execution\r\nmethods. I’ll cover the old school ways and the new, from built-in (and external) binaries, to .NET, to Win32 API\r\ncalls, to PowerShell/PowerView and BloodHound.\r\nThe sample trust architecture I’ll be using for this post is:\r\nThis image was generated with the new TrustVisualizer output (described in the Visualizing Domain\r\nTrusts section). With this new output, green edges mean “within forest”, red means external, and blue means\r\ninter-forest trust relationships. As with @sixdub’s DomainTrustExplorer the edge directions for one-way trust\r\nmean direction of access, not direction of trust.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 6 of 35\n\n.NET Methods\r\n.NET provides us with some nice method wrappers that can enumerate a good chunk of domain and forest trust\r\ninformation. This was the first method that PowerView implemented, before branching into Win32 API and LDAP\r\nmethods.\r\nThe [System.DirectoryServices.ActiveDirectory.Domain] namespace has a GetCurrentDomain() static method\r\nthat returns a System.DirectoryServices.ActiveDirectory.Domain class instance. This class implements\r\nthe GetAllTrustRelationships() method which nicely, “Retrieves all of the trust relationships for this domain.” One\r\nadvantage of this method is its simplicity — the information is laid out in a fashion that is easy to read and\r\nunderstand. One disadvantage is that it doesn’t contain some of the additional information that other enumeration\r\nmethods produce.\r\n“`([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()“`\r\nThis used to be PowerView’s default Get-DomainTrust enumeration method. I recently changed the default\r\nmethod to be LDAP, as this .NET method does not return forest trusts by default, while LDAP enumeration does.\r\nSo in order to execute this method, you now need to run Get-DomainTrust -NET.\r\nHere’s how it looks for my sample domain setup, running the enumeration from sub.dev.testlab.local:\r\nForest trusts are functionally different than domain trusts. So if you want to enumerate any current forest-\u003eforest\r\ntrusts, you need to call on [System.DirectoryServices.ActiveDirectory.Forest] instead. Resulting forest objects also\r\nhave their own GetAllTrustRelationships() method which will return any current forest trusts:\r\n“`([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).GetAllTrustRelationships()“`\r\nThis is implemented as the default enumeration methods for PowerView’s Get-ForestTrust function. Here’s how\r\nit looks for my sample domain setup, again from sub.dev.testlab.local:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 7 of 35\n\nWin32API\r\nYou can also enumerate domain trusts through the DsEnumerateDomainTrusts() Win32 API call which returns\r\na DS_DOMAIN_TRUSTS structure. While the information is a bit more complex than the .NET methods, it\r\nreturns the SID and GUID of the target domain, as well as some useful flags and attributes. The flags\r\nare documented here and will tell you the trust direction, whether the trust is within the same forest, etc. The\r\nattributes are documented here under the TrustAttributes specification, and include things like\r\nWITHIN_FOREST, NON_TRANSITIVE, FILTER_SIDS, and more. FILTER_SIDS is the equivalent of\r\nQUARANTINED_DOMAIN if you ever see that nomenclature.\r\nYou can invoke this method with Get-DomainTrust -API (same sub.dev.testlab.local origination domain):\r\nOf note, this appears to be what nltest.exe uses with its /trusted_domains flag:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 8 of 35\n\nThis is also the method that BloodHound uses to enumerate domain trusts. You can execute this with the\r\nnew SharpHound.ps1 ingestor by using the Invoke-BloodHound -CollectionMethod trusts syntax. Note that this\r\ncan also be combined with -Domain \u003cforeign.domain.fqdn\u003e for foreign trust enumeration as well.\r\nLDAP\r\nDomain trusts are stored in Active Directory as “trusted domain objects” with an objectClass of trustedDomain.\r\nThis means you can use whatever LDAP querying method you would like to find out information about any\r\ndomain trusts that are present by using the LDAP filter (objectClass=trustedDomain).\r\nFor example, here’s dsquery (only available on Windows servers):\r\n“`dsquery * -filter “(objectClass=trustedDomain)” -attr *“`\r\nThe equivalent syntax with Joeware’s Adfind is .\\adfind.exe -f objectclass=trusteddomain.\r\nAnd finally PowerView, which again now uses this LDAP as the default enumeration method for Get-DomainTrust:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 9 of 35\n\nSince this LDAP method is now the default for PowerView’s Get-DomainTrust, I’m going to break down some\r\nof the result properties that might be a bit confusing.\r\nTrustType:\r\nDOWNLEVEL (0x00000001) — a trusted Windows domain that IS NOT running Active Directory. This\r\nis output as WINDOWS_NON_ACTIVE_DIRECTORY in PowerView for those not as familiar with the\r\nterminology.\r\nUPLEVEL (0x00000002) — a trusted Windows domain that IS running Active Directory.This is output\r\nas WINDOWS_ACTIVE_DIRECTORY in PowerView for those not as familiar with the terminology.\r\nMIT (0x00000003) — a trusted domain that is running a non-Windows (*nix), RFC4120-compliant\r\nKerberos distribution. This is labeled as MIT due to, well, MIT publishing RFC4120.\r\nTrustAttributes:\r\nNON_TRANSITIVE (0x00000001) — the trust cannot be used transitively. That is, if DomainA trusts\r\nDomainB and DomainB trusts DomainC, then DomainA does not automatically trust DomainC. Also, if a\r\ntrust is non-transitive, then you will not be able to query any Active Directory information from trusts up\r\nthe chain from the non-transitive point. External trusts are implicitly non-transitive.\r\nUPLEVEL_ONLY (0x00000002) — only Windows 2000 operating system and newer clients can use the\r\ntrust.\r\nQUARANTINED_DOMAIN (0x00000004) — SID filtering is enabled (more on this later). Output\r\nas FILTER_SIDS with PowerView for simplicity.\r\nFOREST_TRANSITIVE (0x00000008) — cross-forest trust between the root of two domain forests\r\nrunning at least domain functional level 2003 or above.\r\nCROSS_ORGANIZATION (0x00000010) — the trust is to a domain or forest that is not part of the\r\norganization, which adds the OTHER_ORGANIZATION SID. This is a bit of a weird one. I don’t\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 10 of 35\n\nremember encountering this flag in the field, but according to this post it means that the selective\r\nauthentication security protection is enabled. For more information, check out this MSDN doc.\r\nWITHIN_FOREST (0x00000020) — the trusted domain is within the same forest, meaning a parent-\r\n\u003echild or cross-link relationship\r\nTREAT_AS_EXTERNAL (0x00000040) — the trust is to be treated as external for trust boundary\r\npurposes. According to the documentation, “If this bit is set, then a cross-forest trust to a domain is to be\r\ntreated as an external trust for the purposes of SID Filtering. Cross-forest trusts are more stringently\r\nfiltered than external trusts. This attribute relaxes those cross-forest trusts to be equivalent to external\r\ntrusts.” This sounds enticing, and I’m not 100% sure on the security implications of this statement\r\n¯\\_(ツ)_/¯ but I will update this post if anything new surfaces.\r\nUSES_RC4_ENCRYPTION (0x00000080) — if the TrustType is MIT, specifies that the trust that\r\nsupports RC4 keys.\r\nUSES_AES_KEYS (0x00000100) — not listed in the linked Microsoft documentation, but according\r\nto some documentation I’ve been able to find online, it specifies that AES keys are used to encrypt KRB\r\nTGTs.\r\nCROSS_ORGANIZATION_NO_TGT_DELEGATION (0x00000200) — “If this bit is set, tickets\r\ngranted under this trust MUST NOT be trusted for delegation.” This is described more in [MS-KILE]\r\n3.3.5.7.5 (Cross-Domain Trust and Referrals.)\r\nPIM_TRUST (0x00000400) — “If this bit and the TATE (treat as external) bit are set, then a cross-forest\r\ntrust to a domain is to be treated as Privileged Identity Management trust for the purposes of SID\r\nFiltering.” According to [MS-PAC] 4.1.2.2 (SID Filtering and Claims Transformation), “A domain can be\r\nexternally managed by a domain that is outside the forest. The trusting domain allows SIDs that are local\r\nto its forest to come over a PrivilegedIdentityManagement trust.” While I have not seen this in the field,\r\nand it’s only supported by domain functional level 2012R2 and above, it also warrants further investigation\r\n🙂\r\nAll of these methods can also be executed against a domain that currently trusts you. Meaning, if your current\r\ndomain has a bidirectional trust with FOREIGN domain, or if the trust is one-way and inbound (meaning said\r\ndomain trusts you and therefore you have some kind of access), you can execute these methods against said\r\ndomain to find the trusts for THAT domain. If you want to do this with PowerView, just supply the -Domain\r\n\u003cdomain.fqdn\u003e parameter, described in more detail in the next section.\r\nData Enumeration Across Trusts With PowerView\r\nLast year I described my ground-up rewrite of PowerView. One of the changes mentioned was that now, any Get-Domain* function uses LDAP enumeration, meaning that we can pull said information from a domain that trusts\r\nus. This is done with the -Domain \u003cdomain.fqdn\u003e parameter:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 11 of 35\n\nSo what’s actually happening under the hood?\r\nFor a long time, I thought that this would “reflect” LDAP queries through a domain controller in your current\r\ndomain and onto domain controllers in the trusting domain. This would have been an awesome way to get around\r\nnetwork boundaries, but sadly I was mistaken. What actually happens is that a referral is returned by the domain\r\ncontroller you are currently communicating with, which instructs your searching method to then bind to the\r\nforeign domain (i.e. the primary domain controller/PDC for that domain). If there is a trust with the foreign\r\ndomain, an inter-realm TGT will be returned that can be used when communicating to the foreign domain.\r\nThis means that if there is network segmentation between the computer you’re currently querying from, and the\r\nPDC for the trusting domain, you won’t be able to retrieve any results \u003e_\u003c\r\nFrom the Kerberos side, “under the hood”, this means that a series of inter-realm referral tickets are automatically\r\nissued that allow our user to eventually request an LDAP service ticket from the target domain. If we use our\r\nsample domain architecture, and currently reside in sub.dev.testlab.local while querying prod.contoso.local,\r\nhere’s how the klist output looks:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 12 of 35\n\nYou can see the inter-realm tickets filtering up the trust chain to testlab.local, and eventually to contoso.local and\r\neventually to prod.contoso.local.\r\nMapping Domain Trusts\r\nThere are few ways I know of to map the “mesh” of one or more trusts that exist in your environment. The first is\r\nthrough the global catalog. I talked about this a bit in my “A Pentester’s Guide to Group Scoping” post, but I’ll\r\nreiterate some of that information here.\r\nThe global catalog is a partial copy of all objects in an Active Directory forest, meaning that some object\r\nproperties (but not all) are contained within it. This data is replicated among all domain controllers marked as\r\nglobal catalogs for the forest. Trusted domain objects are replicated in the global catalog, so we can enumerate\r\nevery single internal and external trust that all domains in our current forest have extremely quickly, and only with\r\ntraffic to our current PDC by running Get-DomainTrust -SearchBase\r\n“GC://$($ENV:USERDNSDOMAIN)” through PowerView. Here’s how that looks running that function\r\nfrom sub.dev.testlab.local domain:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 13 of 35\n\nThis is a lot more results than just Get-DomainTrust !\r\nThe second method is slower, but will provide even more results. Since we can enumerate any trusts that our\r\ncurrent domain context has, and by way of referrals through LDAP, we can query\r\nany (objectClass=trustedDomain) objects from domains that currently trust our domain, then we can keep\r\nissuing these queries for any results and “crawl” any reachable domains. Any domains marked as non-transitive\r\ncan mess these results up, but we can still get a good number of results.\r\nThe PowerView function to do this is Get-DomainTrustMapping (formerly Invoke-MapDomainTrust). These\r\nresults can be exported to a CSV by piping Get-DomainTrustMapping to | Export-CSV -NoTypeInformation\r\ntrusts.csv.\r\nThe last way is through BloodHound/SharpHound. Again, you can execute this with the\r\nnew SharpHound.ps1 ingestor by using the Invoke-BloodHound -CollectionMethod trusts syntax, and this can\r\nbe combined with -Domain \u003cforeign.domain.fqdn\u003e for foreign trust enumeration.\r\nA key thing to remember is that the exact trust mapping you’ll get will depend on the domain you’re currently in.\r\nSince the trust between external.local and sub.dev.testlab.local domain is a one-way non-transitive external\r\ntrust, if you’re querying from external.local you won’t be able to see the trusts that contoso.local has, again\r\nbecause sub.dev.testlab.local won’t repackage your TGT into an inter-realm TGT that can be forwarded onto any\r\nother domain. Also, if you’re trying to enumerate the trusts on a foreign domain, you need to be able to bind to a\r\ndomain controller (usually the PDC/primary domain controller) in the foreign domain you’re querying. So, even if\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 14 of 35\n\nthere is a transitive trust that would allow you to query the information, if network segmentation prevents you\r\nfrom talking to the target foreign domain, you’re out of luck.\r\nVisualizing Domain Trusts\r\nData is one thing, visualizations are another. A few years ago, one of my former workmates, Justin Warner, saw all\r\nthis raw data and build a tool called DomainTrustExplorer that could perform some nodal analysis and\r\nvisualization with PowerView’s mapped trust data.\r\nAs the default trust output has changed, and with BloodHound taking care of nodal analysis for us, I rewrote\r\nJustin’s project into a simplified form that will take the updated trust .CSVs, TrustVisualizer:\r\nThe resulting graphml can be visualized with yEd, as described here. This is how I produced the the previous\r\nvisualization of the sample trust architecture:\r\nAgain, with this new output, green edges mean “within forest”, red means external, and blue means inter-forest\r\ntrust relationships. As with @sixdub’s DomainTrustExplorer the edge directions for one-way trust mean direction\r\nof access, not direction of trust.\r\nWhen using SharpHound to collect the trust data, and BloodHound to visualization it, here’s how the same above\r\ndata looks:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 15 of 35\n\nForeign Relationship Enumeration\r\nNow that we’ve mapped out all domain trusts reachable from the machine we’re querying from, the next step in\r\nthe attack planning phase hits few branches, depending on the specific types of the trusts we’ve encountered.\r\nThese next steps need to be executed for the hop from each each domain to another in the attack path.\r\nIf the next domain hop is in the same forest as the domain we’re pivoting from/through, and we’re able to\r\ncompromise the krbtgt hash of the child domain, then we can use the method described in the\r\nfollowing Trustpocalypse section to compromise the forest root.\r\nIf we’re not able to compromise elevated access in the current/pivot child domain, or if the next step in the trust\r\nattack path is an external/forest trust, then we need to enumerate what users (if any) from the domain we’re a part\r\nof are in groups in the target domain (or the next step in the domain attack path.)\r\nUnfortunately, there are a lot of caveats with this step. The exact nature of the trust your current domain retains\r\nwith the trusting domain you’re querying will affect what information you can retrieve, and the exact methods you\r\ncan use. In general, again, this enumeration heavily depends on whether you’re querying a foreign domain in the\r\nsame forest, or across an external/inter-forest trust. I’ll do my best to explain all the subtleties.\r\nThere are three main ways that security principals (users/groups) from one domain can have access into resources\r\nin another foreign/trusting domain:\r\nThey can be added to local groups on individual machines, i.e. the local “Administrators” group on a\r\nserver.\r\nThey can be added to groups in the foreign domain. There are some caveats depending on trust type and\r\ngroup scope, described shortly.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 16 of 35\n\nThey can be added as principals in an access control list, most interesting for us as principals in ACEs in a\r\nDACL. For more background on ACLs/DACLs/ACEs, check out the “An ACE Up The Sleeve”\r\nwhitepaper.\r\nCase 1: Local Group Membership\r\nThis involves enumerating the local memberships of one or more systems through remote SAM (SAMR)\r\nor through GPO correlation. I won’t cover this case heavily here, but will note that we have had success in the past\r\nwith targeted SAMR enumeration of high value servers or domain controllers for trust-hopping. The PowerView\r\nfunction to do this manually is Get-NetLocalGroupMember \u003cserver\u003e, and BloodHound will do this all\r\nautomatically for you.\r\nCase 2: Foreign Group Membership\r\nThe group membership case gets a bit tricky. The member property of an Active Directory group and\r\nthe memberOf property of a user/group object have a special type of relationship called linked attributes. I\r\ncovered this in more depth in a previous post, but with linked attributes, Active Directory calculates the value of a\r\ngiven attribute, referred to as the back link (e.g. memberOf with users/groups) from the value of another attribute,\r\nreferred to as the forward link (e.g. member with a group). The gist is that group membership is ultimately\r\npreserved within the target group itself in the member property, and this all gets a bit complicated over trusts.\r\nHopefully this will make more sense shortly. Whether or not the memberOf property saved with a user/group\r\nobject reflects their foreign group memberships depends on the nature of the trust and scoping of the foreign\r\ngroup they’re a member in.\r\nHere’s a breakdown of the three group scopings, and which can have what type of foreign members added:\r\nDomain Local Groups can have intra-forest cross-domain users (users in the same forest as the group)\r\nadded as members, as well as inter-forest cross-domain users (foreign security principals.)\r\nGlobal Groups can not have any cross-domain memberships, even within the same forest. So for our\r\npurposes we can ignore these.\r\nUniversal Groups can have any user in the forest as a member, but “foreign security principals” (i.e. users\r\nfrom forest/external trusts) can not be a part of universal groups.\r\nIf a user/group is nested into a group in another domain that’s in the same forest (so a “domain local” or “universal\r\ngroup”) then depending on the target group’s scope the membership might be updated in the\r\nuser/group’s memberOf property. Groups with a “universal” scope have their memberships replicated in the\r\nglobal catalog for the forest, meaning a user’s memberOf will be updated. If the group’s scope the user is added\r\nto is “domain local”, then the user’s memberOf will NOT be updated (in the global catalog), as a group with\r\n“domain local” scope does not have its memberships replicated in the forest. So the only way to tell what a user’s\r\nforeign group memberships are, by solely looking at the user object, is if they are added to a universal group in the\r\nsame forest. However, this also means that if we can bind to the global catalog of a forest, we can enumerate all of\r\nthese specific cross-domain relationships easily.\r\nIf the user is nested in a group in a domain over a forest/external trust, then things are treated a bit differently.\r\nUsers that exist over external or forest trusts can still be added to domain local groups in the specified domain.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 17 of 35\n\nThese users show up as new entries in CN=ForeignSecurityPrincipals,DC=domain,DC=com in the domain to\r\nwhich they’re being added, which are used as a kind of proxy that allows the foreign security identifiers to be\r\nadded to resources in the domain.\r\nAs Microsoft explains it, “When a trust is established between a domain in a forest and a domain outside of that\r\nforest, security principals from the external domain can access resources in the internal domain. Active Directory\r\ncreates a foreign security principal object in the internal domain to represent each security principal from the\r\ntrusted external domain. These foreign security principals can become members of domain local groups in the\r\ninternal domain“. If “domain local” or “group scoping” are foreign to you, check out my previous post on the\r\nsubject.\r\nTl;dr, as I understand it, these ForeignSecurityPrincipals act as aliases for the “real” user that’s external to the\r\ndomain/forest, and it’s the ForeignSecurityPrincipal that’s actually added to groups in the target domain. The SID\r\nof a given ForeignSecurityPrincipal is the same SID as the foreign user, which makes for easy filtering later.\r\nCase 3: Foreign ACL Principals\r\nLuckily most of the ntSecurityDescriptor property of Active Directory objects is (1) accessible to any domain\r\nauthenticated user, and (2) replicated in the global catalog. This means that if from your current domain context,\r\nyou can query the DACLs for all objects in a trusting domain, and filter any ACE entries where a foreign security\r\nprincipal has the given right on the object you’re enumerating.\r\nYou can use PowerView’s Get-DomainObjectACL -Domain \u003cdomain.fqdn\u003e function to retrieve these ACEs,\r\nbut in order to find cross-domain DACL relationships, you will need to filter out principals/SecurityIdentifiers that\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 18 of 35\n\ndo not match the SID of the domain you’re querying. I’ll cover this in a future PowerView PowerUsage post.\r\nOperational Guidance\r\nNote: I’ll also walk over all steps needed in the Case Study section later in the post in case parts of this don’t\r\nmake sense.\r\nIf you’re currently within a child domain within a forest, and DO have elevated access in said child domain, refer\r\nto the Trustpocalypse section.\r\nIf you’re currently within a child domain within a forest, and DO NOT have elevated access in said child domain,\r\nthen you can run PowerView’s Get-DomainForeignUser function to enumerate users who are in groups outside\r\nof the user’s current domain. This is a domain’s “outgoing” access, i.e. users/groups who may have some kind of\r\naccess into other domain groups within the same forest. This function can be useful to also map other intra-forest\r\ndomain user/group relationships:\r\nIf you’re targeting an external/forest domain, or a target domain within the same forest, you can use\r\nPowerView’s Get-DomainForeignGroupMember -Domain \u003ctarget.domain.fqdn\u003e function. This\r\nenumerates groups in the target domain that contain users/groups who are not in the target domain. This is a\r\ndomain’s “incoming” access, i.e. groups in target domain with inbound membership relationships:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 19 of 35\n\nAlso, luckily for us, ForeignSecurityPrincipals are replicated in the global catalog, just like trusted domain objects\r\n(mentioned in the Mapping Domain Trusts section). So if you want to quickly enumerate all foreign security\r\nprincipals (i.e. any inbound foreign groups/users) that are members of groups within a domain within the\r\ncurrent/target forest, you can query any global catalog with an LDAP filter\r\nof ‘(objectclass=foreignSecurityPrincipal)’. And since these foreign principals can only be added to groups with\r\na domain local scope, we can extract the domain the foreign user was added to from the distinguishedname, query\r\nthat domain directly for domain local-scoped groups with members, assuming we have some type of direct or\r\ntransitive trust with that target domain. This allows us to compare the membership of these domain local groups\r\neach against the list of foreign users:\r\n$ForeignUsers = Get-DomainObject -Properties objectsid,distinguishedname -SearchBase \"GC\r\n$Domains = @{}\r\n$ForeignMemberships = ForEach($ForeignUser in $ForeignUsers) {\r\n# extract the domain the foreign user was added to\r\n$ForeignUserDomain = $ForeignUser.SubString($ForeignUser.IndexOf('DC=')) -replace 'DC=',\r\n# check if we've already enumerated this domain\r\nif (-not $Domains[$ForeignUserDomain]) {\r\n$Domains[$ForeignUserDomain] = $True\r\n# enumerate all domain local groups from the given domain that have any membership set\r\nGet-DomainGroup -Domain $ForeignUserDomain -Scope DomainLocal -LDAPFilter '(member=*)' -\r\n# check if there are any overlaps between the domain local groups and the foreign users\r\nif ($($_.member | Where-Object {$ForeignUsers -contains $_})) {\r\n$_\r\n}\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 20 of 35\n\n}\r\n}\r\n}\r\n$ForeignMemberships | fl\r\nThis quickly gives us a mapping of all the foreign user/group nested relationships inbound into our current (or\r\ntarget) forest.\r\nIf you are using BloodHound with its new SharpHound ingestor, you can still use -Domain \u003cdomain.fqdn\u003e with\r\nthe ingestor combined with the -CollectionMethod options of ‘Group’, ‘LocalGroup’, and/or ‘ACL’. BloodHound\r\nmodels user/group nodes with the name@\u003cdomain.fqdn\u003e syntax in the schema. This removes the requirement of\r\nhaving to perform complex analytics to extract these relationships after the data has been collected.\r\nIf user@dev.testlab.local is a member of group@testlab.local, that memberOf relationship is automatically\r\nmodeled. If that nested group relationship shows up in any attack paths, it will be automatically included in your\r\ngraph with no extra effort.\r\nMakes perfect sense, right? 🙂 This is a complex topic if you’re not familiar, so reread the previous section a few\r\ntimes until it makes sense how to tease out these cross-domain relationships. Check out the Case Study section\r\nfor a realistic walk through with the reference architecture I’ve used throughout this post.\r\nThe Trustpocalypse — SID Hopping Up Intra-Forest Trusts\r\nThis is one of my favorite things I’ve learned about in the last few years in security. Just as most people remember\r\nthe first time they saw Mimikatz extract a plaintext password out of memory, the memory of when I realized what\r\nthis attack entailed is seared into my mind.\r\nIt started as many of my brain-blowing moments have, by viewing a tweet from Benjamin Delpy in June of 2015,\r\nand at first not understanding the implications:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 21 of 35\n\nAfter chatting with Benjamin to confirm what I thought the implications were, his response was “Sorry for your\r\nhead :)”\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 22 of 35\n\nThis is all thanks to work that Benjamin and Sean Metcalf worked on to make Golden tickets even more “golden”.\r\nI blogged about this back in August of 2015 after their work was released in a post titled “The Trustpocalypse.”\r\nPrevious to this work, our strategy was to map out foreign user/group memberships and hop from child trust up to\r\nthe forest root “by hand”, often a painstaking process in large environments with lots of domains. As described in\r\nthe Trust Attack Strategy section, we always interpreted trust as “flowing down” from the forest root to child\r\ndomains due to the “Enterprise Admins” group. However, Microsoft has stated for years that “the forest is the\r\nsecurity boundary for Active Directory“, and an attack against intra-forest domains has been known since (at least)\r\n2005.\r\nBut first, in order for this to make complete sense, I have to explain sidHistory and the SID filtering security\r\nmechanism, and what this all means for domains within a forest.\r\nsidHistory was added with Windows 2000 Active Directory, and was meant to facilitate the migration of users\r\nfrom one domain to another. If a user is migrated, their old security identifier (SID), along with the SIDs of any\r\ngroup they were previously a part of, can optionally be added to the sidHistory attribute of their new user account.\r\nWhen the new user attempts to access a resource, “if the SID or the SID history matches, access to the resource is\r\ngranted or denied, according to the access specified in the ACL.” Meaning, any group/old user SID that is set in a\r\nuser’s sidHistory property grants them access as if they were that user or a member of those groups.\r\nDue to how trusts work within an Active Directory forest, the sidHistory property (“ExtraSids” in the PAC) is\r\nrespected within the domains of a forest because those SIDs are not filtered out in cross-domain referrals by the\r\n“SID Filtering” protection. So any user in a child domain that has their sidHistory/ExtraSids set to, say, the\r\n“Enterprise Admins” SID (a group that exists only in the forest root) will effectively function as if they are an\r\nenterprise administrator. As Microsoft has known this is an issue, and the knowledge has been public since at\r\nleast this 2005 ITPro Windows article and almost certainly before, sidHistory is a protected attribute that is\r\nextremely difficult to modify.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 23 of 35\n\nPreviously, abuse of this involved a pretty complex process, and included modifying the sidHistory in the Active\r\nDirectory database (ntds.dit) of the associated domain. There’s more detail about exactly why/how this works in\r\nthe Epilogue: SID Filtering section.\r\nTHIS IS WHY THE FOREST IS THE “TRUST BOUNDARY” IN ACTIVE DIRECTORY, NOT THE\r\nDOMAIN!\r\nBenjamin and Sean realized that with the introduction of Mimikatz’ Golden Tickets, an attacker could set\r\nthe ExtraSids section of the KERB_VALIDATION_INFO structure created for the ticket (the structure that\r\n“defines the user’s logon and authorization information provided by the DC“). The ExtraSids section is described\r\nas “A pointer to a list of KERB_SID_AND_ATTRIBUTES structures that contain a list of SIDs corresponding to\r\ngroups in domains other than the account domain to which the principal belongs” (the\r\nKERB_SID_AND_ATTRIBUTES structure is defined here.)\r\nThis means that if an attacker compromises “Domain Administrator” rights (or equivalent, actually just any\r\naccount that can DCSync 😉 in ANY child domain in the forest for just 5 minutes, the krbtgt hash of the child\r\ndomain can be retrieved, and /sids:\u003csid_of_enterprise_admins_in_forest_root\u003e can be added to the Mimikatz\r\nconstructed ticket without modifying the Active Directory database. This gives the attacker the ability to “hop up”\r\nthe forest trust relationship and compromise the forest root domain.\r\nIf this is your first time hearing about this technique, as Benjamin said, “Sorry for your head. :)”\r\nFor our operational attack strategy, this means that if we are currently in a child domain and can compromise\r\nDCSync/DA access, or if we can compromise this level of access in any child domain along our attack chain, we\r\ncan forgo the burdensome foreign relationship enumeration to hop up the trust to instantly compromise the forest\r\nroot. We have done this in the field, and yes, it is awesome. 🙂 For operational advice/guidance, check out\r\nmy previous Trustpocalypse post from 2015.\r\nThis will only work for hopping between trusts within a forest. This will not work for external or inter-forest\r\ntrusts due to SID filtering, described in more detail in the Epilogue: SID Filtering section at the end of the post.\r\nA Case Study\r\nSo, consider again the sample trust diagram:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 24 of 35\n\nSay we land an account in external.local. Since sub.dev.testlab.local trusts external.local, external.local can\r\nquery information from sub.dev.testlab.local, while SUB cannot do the same to EXTERNAL. From the external\r\ncontext, we can query the trusts that SUB has:\r\nBut this only returns the direct trusts that sub.dev.testlab has with other domains\r\n(dev.testlab.local and external.local). If we can query the global catalog (not always possible)\r\nfrom sub.dev.testlab and return all domain trusts in the entire forest!\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 25 of 35\n\nNote that because since this is a one-way, non-transitive external trust into sub.dev.testlab.local, we can’t query\r\nthe trusts that contoso.local has from the EXTERNAL context, as our Kerberos traffic will not be properly\r\nreferred. This is what this error usually means, in case you run across it:\r\nSo, from here we would then run Get-DomainForeignGroupMember -Domain sub.dev.testlab.local to see if\r\nany groups in SUB contained members in EXTERNAL:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 26 of 35\n\nFrom there, we would attempt targeted account compromise to hop the trust into sub.dev.testlab.local. The Get-DomainForeignUser command would be of no use here, due to the caveats about linked-value replication and\r\ntrusted described in the Foreign Relationship Enumeration section.\r\nHowever, because external.local -\u003e sub.dev.testlab.local is an external trust relationships, it is implicitly non-transitive, so couldn’t query the domain local group memberships of dev.testlab.local or testlab.local.\r\nIf we were then able to compromise domain admin (or equivalent) credentials in sub.dev.testlab.local, we could\r\nbuild a sidHistory-trust-hopping Golden Ticket as described in the “Trustpocalypse” section to compromise\r\nthe testlab.local forest root domain. If we weren’t able to procure elevated access, we would run Get-DomainForeignUser to see if any users from sub.dev.testlab.local had access into other groups in the forest.\r\nAgain, remember the previous information about scoping- only universal group memberships will be reflected\r\nhere:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 27 of 35\n\nWe would also run Get-DomainForeignGroupMember -Domain dev.testlab.local and Get-DomainForeignGroupMember -Domain testlab.local to see that groups in those other forest domains had\r\n“incoming” access:\r\nOnce/if we were able to compromise part or all of the testlab.local forest root through either of the previous\r\napproaches, we would then run Get-DomainForeignGroupMember -Domain contoso.local and Get-DomainForeignGroupMember -Domain prod.contoso.local to see if there were any users in the TESTLAB\r\nforest that had foreign group membership in the CONTOSO forest.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 28 of 35\n\nAlong the way, we would could run Get-NetLocalGroupMember \u003cforeign,server\u003e against a targeted selection\r\nof servers (including DCs) to see if any users crossed the boundary that way via machine local groups. We could\r\nalso use targeted Get-DomainObjectACL -Domain \u003cforeign.domain\u003e with various filters to check for foreign\r\nACL memberships.\r\nOr we could just pull everything with BloodHound, and rely on the schema to model the cross-forest hops. 🙂\r\nSidenote: Forging Inter-Realm Trust Tickets\r\nIt is possible to forge inter-realm trust tickets to exploit trust relationships. As Sean covered this extremely well in\r\nhis “It’s All About Trust” post, I’ll refer you to his documentation for more operational details, and will just cover\r\nthe implications of this technique and how it fits into our trust attack strategy.\r\nRecall the explanation of how Kerberos works across trusts:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 29 of 35\n\nSo when the user presents this inter-realm ticket-granting-ticket referral to the foreign domain, again signed by the\r\ninter-realm trust key, the user’s TGT is included within it. And again, because the foreign domain trusts the\r\ndomain that that issued the referral ticket, the foreign domain trusts the user’s TGT and all its included\r\ninformation to be accurate.\r\nAgain, in English, when the foreign domain decrypts the referral ticket with the negotiated trust key, it sees the\r\nuser’s TGT and says “OK, the other domain already authenticated this user and said this is who they say they\r\nare/these are the groups the user is in, so I’ll trust this is accurate because I trust this domain.”\r\nSo, if we can retrieve the hash of the inter-realm trust key, a referral ticket can be forged (as Sean describes) that\r\nallows us to pretend to be any user from the first domain when requesting access to the second domain. This hash\r\nretrieval can be done through normal password dumping or through DCSync, by querying\r\nthe FOREIGN_DOMAIN_SHORTNAME$ account:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 30 of 35\n\nHowever, if we can retrieve the inter-realm trust key, then in pretty much all cases we can pull the krbtgt hash of\r\nthe referring domain. If we have this, we can construct a ticket for user referring domain, pretending to be any\r\nuser we want to the foreign domain. This is why I haven’t had a need to forge inter-realm trust referrals in the\r\nfield, but there is one specific instance where it gets interesting.\r\nBack in 2015, after everyone started to fully realize the implications of Golden Tickets, Microsoft released\r\nscripts that allow organizations to change the password of the krbtgt account. In order for this to be effective for a\r\nsingle-domain forest, the password has to be changed twice. Now, because of the implementation of the\r\nsidHistory-hopping attack, the password for the krbtgt account in EVERY domain in the forest, twice.\r\nSay an organization does this, and rotates the passwords for every elevated account in every domain in the forest,\r\nare they safe? Well, while inter-realm trust keys automatically rotate every 30 days according to section 6.1.6.9.6.1\r\nof the Active Directory Technical Specification, they aren’t rotated when the krbtgt account changes. So if an\r\nattacker has the inter-realm keys in their possession, they can still use the sidHistory approach to hop up a trust, as\r\nSean details. Then again, there’s a million and one other ways to backdoor Active Directory. ¯\\_(ツ)_/¯\r\nSo there’s only one solution if you want to be sure (thanks @gentilkiwi 🙂\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 31 of 35\n\nAnother Sidenote: Kerberoasting Across Domain Trusts\r\nWe love Kerberoasting. Introduced by Tim Medin in 2014, we ‘roast on a ton of our engagements. And if we have\r\na domain that trusts us, we can roast across these trust boundaries, with one minor tweak in some situations.\r\nWhen using .NET’s System.IdentityModel.Tokens.KerberosRequestorSecurityToken class (and then\r\nits .GetRequest() method), we specify a service principal name (SPN) to request a TGS-REP for, and subsequently\r\nuse the GetRequest() to retrieve the bytes for the AP-REQ that’s intended to be sent to the target service. This AP-REQ contains the service ticket that we then extract and use for offline Kerberoasting/password cracking.\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 32 of 35\n\nThe documentation for the KerberosRequestorSecurityToken.ServicePrincipalName nicely describes the format as\r\n“host/\u003chostname\u003e@\u003cdomain\u003e or \u003chostname\u003e, where hostname is the name of the computer hosting the target\r\nWeb service and domain is the fully-qualified domain name of the Kerberos realm in which the host computer\r\nresides.” So if you have any issues with Kerberoasting across trusts (particularly external and forest trusts), try\r\nusing the SERVICE/host.domain.com@domain.com format and you may have more success. This is possible\r\nwith PowerView’s Get-DomainSPNTicket, the function that Invoke-Kerberoast is built on.\r\nEpilogue: SID Filtering\r\nSo we previously talked about how/why the forest is the trust boundary in Active Directory, not the domain. A big\r\npart of this is the security protection I’ve alluded to several times previously called SID Filtering. The best\r\nreference for SID filtering is the [MS-PAC] “Privilege Attribute Certificate Data Structure” documentation,\r\nspecifically section 4.1.2.2 “SID Filtering and Claims Transformation.” I will do my best to explain a few salient\r\npoints.\r\nWhen a user’s TGT is presented to the new domain through a referral, that TGT contains a privileged attribute\r\ncertificate (PAC) that contains, among other things, the user’s security identifier (SID), the security identifiers of\r\ngroups they are in, and anything present in the previously discussed sidHistory field (i.e. the ExtraSids PAC part\r\ndescribed in the Trustpocalypse section). This security identification information in the PAC is parsed and\r\nanalyzed by a trusting domain, and various filters are executed depending on the type of the trust.\r\nSIDs matching particular patterns are rejected by the trusting domain under various circumstances, as a security\r\nprotection. SID filtering is meant to stop malicious users with elevated credentials in a trusted domain/forest from\r\ntaking control of a trusting domain/forest. This is also described in Microsoft’s “Security Considerations for\r\nTrusts” documentation.\r\nThere is a set of SIDs that are set to ‘AlwaysFilter’, meaning they are always filtered out by a trusting domain, no\r\nmatter the trust type. The main SID we’re interested in, “Enterprise Admins” (S-1–5–21-\u003cDomain\u003e-519), the one\r\nthat allows us to execute the sidHistory-hopping attack, is set to “ForestSpecific” for filtering. As Microsoft\r\ndescribes, “The ForestSpecific rule is for those SIDs that are never allowed in a PAC that originates from out of\r\nthe forest or from a domain that has been marked as QuarantinedWithinForest, unless it belongs to that domain.”\r\nAgain, this explains why the forest is the trust boundary, not the domain, as this elevated SID (along with many\r\nothers) can not be passed across a trust boundary except if the target domain is within the same forest.\r\nQuarantinedWithinForest, huh? It so happens that domains within a forest can be set as “quarantined”, which\r\nimplements a version SID filtering for the domain, even though it is within the forest. However, as the\r\ndocumentation states, “The only SIDs that are allowed to be passed from such a domain are the “Enterprise\r\nDomain Controllers” (S-1–5–9) SID and those described by the trusted domain object (TDO).” So, since the\r\n“Enterprise Domain Controllers” SID is NOT filtered out for intra-forest quarantined domains, there is still a way\r\nto “hop up” the forest trust chain and compromise the forest root:\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 33 of 35\n\nThis is something I attempted to explain a few years ago without properly understanding the problem, but it makes\r\na bit more sense now after reading heaps of Microsoft documentation 🙂\r\nWrapup\r\nTrusts are not a simple topic. Most pentesters (and many sysadmins!) do not properly understand trusts and the\r\nrisk exposed by various trust misconfigurations. Unfortunately for us, some bad guys do, and trusts have been\r\nabused since nearly the beginning of Active Directory to exploit access in one domain in order to pivot into\r\nanother.\r\nIf your domain trust architecture is setup incorrectly, then what’s the answer? Unfortunately, as with many major\r\narchitectural flaws of this nature, there is not a simple fix. Rearchitecting a major Active Directory deployment\r\ncan be a long, expensive, and painful process, but there is still a guiding light: the Enhanced Security\r\nAdministrative Environment (ESAE), commonly referred to as “Red Forest”, which is a secured Active Directory\r\narchitecture that mitigates an enormous number of Active Directory vulnerabilities/misconfigurations. While\r\nMicrosoft has published aspects of the architecture, the only way that I currently know how have an ESAE/Red\r\nForest is to pay Microsoft to implement it for you. ¯\\_(ツ)_/¯\r\nI would love to eventually publish guidance on how organizations implement a “red-forest-esque” environment,\r\nthat while not “officially” compliant with the reference architecture, would still be better than many organization’s\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 34 of 35\n\ncurrent implementations. If anyone has documentation or guidance on how to do practically do this, please contact\r\nme (@harmj0y or will [at] harmj0y.net) and I will happily get that kind of information out there.\r\nSource: https://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nhttps://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944\r\nPage 35 of 35",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://posts.specterops.io/a-guide-to-attacking-domain-trusts-971e52cb2944"
	],
	"report_names": [
		"a-guide-to-attacking-domain-trusts-971e52cb2944"
	],
	"threat_actors": [],
	"ts_created_at": 1775434948,
	"ts_updated_at": 1775791313,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a9f884ecc28345e66e289e8895bc641365e092a4.pdf",
		"text": "https://archive.orkl.eu/a9f884ecc28345e66e289e8895bc641365e092a4.txt",
		"img": "https://archive.orkl.eu/a9f884ecc28345e66e289e8895bc641365e092a4.jpg"
	}
}