SID Filter Bypass
SID Filtering is a mechanism that filters out all SIDs with a Relative Identifier (RID) of 1000
in cross-forest configurations.
A CVE was discovered in 2020 that allowed to bypass SID Filtering to compromise hosts in a trusted forests. The vulnerability was patched in February of the same year.
Transitive trust scenario
A Transitive trust is configured to propagate authentication requests and permissions across all domains in the forest, providing seamless access to resources regardless of the domain in which they reside; this greatly simplifies shearing resources withing a forest.
Let's say we have domain.com
and otherdomain.com
that form a two-way transitive trust between them, domain.com
has a child domain, child.domain.com
; the transitive nature of the relationship between the first two domains will extend the trust to the child domain as well.
This rule applies to new subdomains as well: if we were to add a new subdomain to domain.com
, otherdomain.com
will fetch the SID of the newly-created domain by making a NetrGetForestTrustInformation
call to the domain controller. The results of this query are returned in a format called LSA_FOREST_TRUST_RECORD
and are stored in a TDO in otherdomain.com
.
The ftinfo allows to extract information about the trust by decrypting the msDS-TrustForestTrustInfo
binary field which we can access from the Active Directory Users and Computers
utility (otherdomain.com > domain.com > Attribute Editor > msDS-TrustForestTrustInfo
); the contents of the attribute have to be placed on line 14 of the script and running it will parse the data into a readable format.
Exploiting CVE-2020-0665
Exploiting this vulnerability requires the following requirements:
DC01 and DC02 must have a Two-way Transitive Trust
DC01 must have a Child Domain (subdomain)
DC02 has at least one domain joined
member server
orworkstation
From a high-privilege position in the domain.com
forest we can manipulate the trust relationships by adding a malicious SID to the list of the subdomains for domain.com
or modifying an existent one; as described earlier, otherdomain.com
will query for the SID of the new subdomain, propagating the trust through-out the forest.
The third requirement stems from the fact that, when querying an individual member server
or workstation
in a domain about the number of domains it trusts, it typically reports two. One domain pertains to the Active Directory
domain to which the workstation or server belongs, while the other refers to the local domain
unique to that specific machine. This local domain, residing in the Security Accounts Manager (SAM)
hive, houses local accounts
and groups
, including the widely recognized RID 500
account, which represents the built-in Administrator
account commonly targeted in Pass-the-Hash attacks.
Active Directory does not manage these local domains on member systems
, and therefore, it remains unaware of their existence. Consequently, each Active Directory domain will have as many local domains as the number of systems joined to it, reflecting the diversity of local accounts and configurations across the network.
The steps of the attack are:
Fake a new domain in forest A that has the same SID as the local domain on a server in forest B
Wait for forest B to pick up the new SID and add it to the allowed SIDs
Create an inter-realm ticket that includes the SID of the local administrator account of the server in forest B, and give this to the DC in forest B
See if forest B gives us a ticket that includes the SID of the server in forest B
Connect to the server in forest B with our service ticket having administrative permissions
We cannot compromise a Domain Controller in a Trusted forest (Forest-B) because while a Domain Controller has a local domain in SAM, it is only active during recovery mode, which does not satisfy the conditions necessary for the attack to work.
Let's imagine the following setup
We successfully compromised Forest A and want to compromise ANY02
in Forest B.
Mind that ANY02
represents ANY domain computer in the second forest except the DC.
Enumerate the local SID of ANY02 with credentials from
domain.com
Enumerate the domain SID for
child.domain.com
Enumerate the domain SID for
domain.com
Enumerate the GUID for
otherdomain.com
Get hashes to request Inter-Realm ticket for
otherdomain.com
The first 5 steps allowed us to enumerate all the needed information, the following ones will work on making otherdomain.com
accept our SID for future inter-realm ticket requests: to do it we will use this Frida Interception script which will inject itself into the lsass.exe
process in the domain.com
'd DC and hook the NetrGetForestTrustInformation
(which is called by otherdomain.com
every 24 hours to get the SID of the other subdomains in Forest A) and replace the SID of an existing subdomain (in this case child.domain.com
) with the SID of the host we want to compromise (ANY02.otherdomain.com
).
In order to set up the script we need update the buf1
and newsid
variables with the hexadecimal representation of child.domain.com
and ANY02's SIDs respectively; to convert the SIDs to hexadecimal form we can use a custom python script
Now we execute the script from a SYSTEM
shell
and wait for otherdomain.com
to query the DC for the new SIDs so that the changes can take place and be applied to the trust.
At this point we can request a golden ticket with the extra SID of ANY02
and retrieve a TGS for ANY02
Now we can access ANY02 using the ticket in memory.
Last updated