Security Focus: sIDHistory / sID Filtering Sanity Check - Part 2

Last week, as well as posting my 100th blog post, I also talked about using PowerShell to look for sIDHistory in your forest.

This week, I'll show you how to check whether sID Filtering is disabled on your trusts. With sID Filtering disabled the trusting domain will accept sIDs from domains other than the trusted domain. This relaxed approach enables the use of sIDHistory, but could also lead to an elevation of privilege across the trust.

This piece of PowerShell picks out trusts that have sID Filtering disabled. It will differentiate between External Trusts and Forest Trusts. It reports on the outgoing trusts of trusting domains.

(Get-ADForest).Domains | ForEach-Object {

$Domain = $_

Get-ADTrust -Filter * -Server $Domain | ForEach-Object {

if (($_.ForestTransitive) -and ($_.SIDFilteringForestAware)) {

Write-Output "FOREST_TRUST: sID Filtering is disabled on trustedDomain object '$($_.DistinguishedName)' in $Domain"

}

elseif ((-not ($_.ForestTransitive)) -and (-not ($_.SIDFilteringQuarantined)) -and (-not ($_.IntraForest))) {

Write-Output "EXTERNAL_TRUST: sID Filtering is disabled on trustedDomain object '$($_.DistinguishedName)' in $Domain"

}

}

}

 

In the below sample a parent and child domain in a forest were evaluated. An external trust and a forest trust were found to not have sID Filtering enabled.

 

The code uses Get-ADTrust and evaluates the returned objects' attributes to determine the trust type and whether sID Filtering is disabled. Primarily, we're looking at the sIDFilteringForestAware property for the status of sID Filtering on a forest trust and the sIDFilteringQuarantined property for the status of sID Filtering on an external trust. If sIDFilteringForestAware is $true then sIDFiltering is disabled on the forest trust. If sIDFilteringQuarantined is  $false then sIDFiltering is disabled on the external trust.

I've also updated my trust status script to report on sID Filtering status:

Active Directory Trust Status Report (with sID Filtering status)

 

A few things to note:

  • The script tests the domain of the targeted DC
  • The script tests all trusts types, not just Forest and External. Intra-Forest trusts will flag as having sID Filtering (quarantine) disabled - this is default.
  • The script will identify Forest and Intra-Forest trusts. External trusts will not be called out but can be assumed to be those that are marked as both false in IS_FOREST and IS_INTRA_FOREST. NB - other trust types, e.g. shortcut, will flag as false / false too.
  • The script doesn't use Get-ADTrust, rather it uses the WMI / CIM Microsoft_DomainTrustStatus class from the Root/MicrosoftActiveDirectory namespace. This exposes the trustAttributes property of each Trusted Domain Object (TDO). The trustAttributes property is then used to determine the whether sID Filtering is disabled on the trust. For a forest trust, if a value of 64 is contained within the property then we have forest aware sIDFIltering disabled on the trust. For an external trust if a value of 4 is contained within the trustAttributes property then we have sID Filtering quarantine enabled on the trust. Here's some of the code:

 

#Trust Attributes

New-Variable -Name sIDFiltering_Quarantined -Value 4 -Option Constant #sID Filtering applied (quarantine)

New-Variable -Name Forest_Transitive -Value 8 -Option Constant #Forest Transitive Trust

New-Variable -Name Intra_Forest -Value 32 -Option Constant #Intra Forest Trust

New-Variable -Name sIDFiltering_ForestAware -Value 64 -Option Constant #sID Filtering applied (forest aware)

 

#Get sIDFiltering status

$ForestAware = $false

$Quarantine = $false

 

#Check for sID Filtring disabled on forest trusts

if ($Trust.trustAttributes -band $sIDFiltering_ForestAware) {

$ForestAware = $true

}

#Check for sID FIltering enabled on trusts

if ($Trust.trustAttributes -band $sIDFiltering_Quarantined) {

$Quarantine = $true

}

 

Our integers of 4 and 64 are assigned to constants for human-readability in the script body. We then use the bitwise AND ( -band) operator with if statements to check whether 4 or 64 are part of the integer contained within the trustAttributes property. If 4 is present the $ForestAware variables is set to true. If 64 is present the $Quarantine variables is set to true. These variables are then used in the line added to the CSV report. Here's what we end up with:

 

The first thing to check is whether we are dealing with a Forest trust - is IS_FOREST set to true? If it is, then the SIDFILTERING_FORESTAWARE_DISABLED should be false. If SIDFILTERING_FORESTAWARE_DISABLED is true then sID Filtering is disabled. Next, check for those trusts that have IS_FOREST and IS_INTRA_FOREST both set to false. These are likely to be external trusts. SIDFILTERING_QUARANTINE_ENABLED should be set to true - if it isn't, then sID FIitering is disabled

Report generation can be task scheduled and checked historically. The forest check one-liner at the top of this post can be performed whenever you like... for immediate peace of mind.

And, so ends this two-parter. HTH!