Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save zjorz/06a5cfa5211aaf40092effe9647fdd08 to your computer and use it in GitHub Desktop.

Select an option

Save zjorz/06a5cfa5211aaf40092effe9647fdd08 to your computer and use it in GitHub Desktop.
#######
# Finding All Candidate EXPLICIT Allow ACEs To Investigate For dMSA Abuse In AD Domain
#######
Clear-Host
# Execution Date/Time
$datetime = Get-Date
# Local Computer Domain
$fqdnADDomainOfComputer = $(Get-WmiObject -Class Win32_ComputerSystem).Domain # Focusing On The AD Domain FQDN Of The Computer
# List Of SIDs To Filter Out
# REMARK: To Filter Out Additional SIDs, Add The Well-Known Object SID(s) (Like e.g. Administrators) Or RID Specific Object SID(s) (Like e.g. Domain Admins)
$sidsToFilterOut = @()
$sidsToFilterOut += "S-1-5-32-544" # ADMINISTRATORS
$sidsToFilterOut += "S-1-3-0" # CREATOR OWNER
$sidsToFilterOut += "S-1-5-9" # NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS
$sidsToFilterOut += "S-1-5-18" # NT AUTHORITY\SYSTEM
$sidsToFilterOut += "DOMAIN_SID-512" # Domain Admins ("DOMAIN_SID" Will Be Replaced By The Respective SID Of The AD Domain)
$sidsToFilterOut += "FOREST_SID-519" # Enterprise Admins ("FOREST_SID" Will Be Replaced By The Respective SID Of The Root AD Domain)
# Locate An RWDC For The Current AD Domain And The Forest Root AD Domain
$dcLocatorFlag = [System.DirectoryServices.ActiveDirectory.LocatorOptions]::"ForceRediscovery", "WriteableRequired" # Writeable DC
$adDomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain", $fqdnADDomainOfComputer) # AD Domain Context
$adDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($adDomainContext) # AD Domain Object
$rwdcFQDN = $adDomain.FindDomainController($dcLocatorFlag).Name # RWDC In The AD Domain
$adForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() # AD Forest Object
$rwdcFQDNDNM = $adForest.NamingRoleOwner.Name # RWDC In Forest Root With The Domain Naming Master FSMO Role
$rwdcFQDNSCH = $adForest.SchemaRoleOwner.Name # RWDC In Forest Root With The Schema Master FSMO Role
# Get The Default Naming Context, The Root Domain Naming Context, The Domain Object SID And The Root Domain Object SID From The RootDSE
$rootDSE = [ADSI]"LDAP://$rwdcFQDN/RootDSE" # Root Dse Of RWDC In The AD Domain
$domainNCDN = $rootDSE.defaultNamingContext # AD Domain NC DN, a.k.a. The Default Naming Context
$domainFQDN = $domainNCDN.Replace(",DC=",".").Replace("DC=","") # AD Domain FQDN
$rootDomainNCDN = $rootDSE.rootDomainNamingContext # Root AD Domain NC DN, a.k.a. The Root Naming Context
$schemaNCDN = $rootDSE.schemaNamingContext # Schema NC DN, a.k.a. The Schema Naming Context
$domain = [ADSI]"LDAP://$rwdcFQDN/$domainNCDN" # AD Domain Object
$domainSid = $(New-Object Security.Principal.SecurityIdentifier($($domain.objectSid),0)).ToString() # AD Domain ObjectSID
$forest = [ADSI]"LDAP://$rwdcFQDNDNM/$rootDomainNCDN" # Root AD Domain Object
$forestSid = $(New-Object Security.Principal.SecurityIdentifier($($forest.objectSid),0)).ToString() # Root AD Domain ObjectSID
$schema = [ADSI]"LDAP://$rwdcFQDN/$schemaNCDN" # AD Schema Object
# List Of Security Principals To Filter Out, Translated From ObjectSIDs To Also Support Non-English ADs
$securityPrincipalsToFilterOut = @()
$sidsToFilterOut | ForEach-Object {
$sid = $_.Replace("FOREST_SID","$forestSid").Replace("DOMAIN_SID","$domainSid")
$objSID = New-Object System.Security.Principal.SecurityIdentifier($sid)
$securityPrincipal = ($objSID.Translate([System.Security.Principal.NTAccount])).Value
$securityPrincipalsToFilterOut += $securityPrincipal
}
# Query The Schema Naming Context For Object Classes That Can Have a Child msDS-DelegatedManagedServiceAccount
$dsDirSearcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$dsDirSearcher.SearchRoot = "LDAP://$rwdcFQDN/$schemaNCDN"
$dsDirSearcher.SearchScope = "OneLevel"
$dsDirSearcher.Filter = "(objectClass=classSchema)"
[void]($dsDirSearcher.PropertiesToLoad.Add("lDAPDisplayName"))
[void]($dsDirSearcher.PropertiesToLoad.Add("name"))
[void]($dsDirSearcher.PropertiesToLoad.Add("possibleInferiors"))
$listOfPossibleParentObjectTypesToInvestigate = @()
$dsDirSearcher.FindAll() | Where-Object {$_.Properties.possibleinferiors -eq "msDS-DelegatedManagedServiceAccount"} | ForEach-Object {
$listOfPossibleParentObjectTypesToInvestigate += $_.Properties.ldapdisplayname
}
# Query The Default Naming Context
$dsDirSearcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$dsDirSearcher.SearchRoot = "LDAP://$rwdcFQDN/$domainNCDN"
$dsDirSearcher.SearchScope = "Subtree"
$ldapFilterQueryDefaultNC = "(|"
$listOfPossibleParentObjectTypesToInvestigate | ForEach-Object {
$ldapFilterQueryDefaultNC += "("
$ldapFilterQueryDefaultNC += "objectClass=$_"
$ldapFilterQueryDefaultNC += ")"
}
$ldapFilterQueryDefaultNC += "(objectClass=msDS-DelegatedManagedServiceAccount)"
$ldapFilterQueryDefaultNC += ")"
$dsDirSearcher.Filter = $ldapFilterQueryDefaultNC
[void]($dsDirSearcher.PropertiesToLoad.Add("allowedChildClasses"))
[void]($dsDirSearcher.PropertiesToLoad.Add("distinguishedName"))
[void]($dsDirSearcher.PropertiesToLoad.Add("canonicalName"))
[void]($dsDirSearcher.PropertiesToLoad.Add("nTSecurityDescriptor"))
[void]($dsDirSearcher.PropertiesToLoad.Add("objectClass"))
$listOfACEsToInvestigate = @()
$dsDirSearcher.FindAll() | Where-Object {
$_.Properties.distinguishedname[0] -notlike "*CN=System,$domainNCDN" -And `
($_.Properties.allowedchildclasses -eq "msDS-DelegatedManagedServiceAccount" -Or `
$_.Properties.objectclass -eq "msDS-DelegatedManagedServiceAccount")
} | ForEach-Object {
$objDN = $_.Properties.distinguishedname[0]
$objCanonicalName = $_.Properties.canonicalname[0]
$objClass = ($_.Properties.objectclass)[$($_.Properties.objectclass | Measure-Object).Count - 1]
$objNTSecurityDescriptor = $_.Properties.ntsecuritydescriptor[0]
$adSecurity = $null
$adSecurity = New-Object System.DirectoryServices.ActiveDirectorySecurity
$adSecurity.SetSecurityDescriptorBinaryForm($objNTSecurityDescriptor)
# Check The Current Owner Of The Object
If ($adSecurity.Owner -notin $securityPrincipalsToFilterOut) {
$aceToInvestigate = New-Object -TypeName System.Object
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Distinguished Name" -Value $objDN
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Canonical Name" -Value $objCanonicalName
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Object Class" -Value $objClass
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Security Principal" -Value $($adSecurity.Owner)
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Permissions" -Value "Owner Of Object"
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Applies To" -Value "Not Applicable"
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Attributes" -Value "Not Applicable"
$listOfACEsToInvestigate += $aceToInvestigate
}
# Check The Current ACEs Of The Object
$adSecurity.Access | Where-Object {
$_.AccessControlType -eq "Allow" -And ` # Allow ACEs Only
$_.IdentityReference.Value -notin $securityPrincipalsToFilterOut -And ` # Only Security Principals NOT In The Filter Out List
$_.IsInherited -eq $false -And ` # Explicit (Non-Inherited) ACEs Only!
( `
($_.ActiveDirectoryRights -match "CreateChild" -And `
($_.ObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -Or ` # msDS-DelegatedManagedServiceAccount Objects
$_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000") ` # msDS-DelegatedManagedServiceAccount Objects
) -Or `
(($_.ActiveDirectoryRights -match "GenericAll" -Or `
$_.ActiveDirectoryRights -match "WriteDacl" -Or `
$_.ActiveDirectoryRights -match "WriteOwner") -And `
($_.InheritedObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -Or ` # msDS-DelegatedManagedServiceAccount Objects
$_.InheritedObjectType.Guid -eq "00000000-0000-0000-0000-000000000000" ` # All Objects (When Defined On A Container/OU)
)) -Or `
($_.ActiveDirectoryRights -match "WriteProperty" -And `
($_.ObjectType.Guid -eq "2f5c138a-bd38-4016-88b4-0ec87cbb4919" -Or ` # msDS-DelegatedMSAState Attribute
$_.ObjectType.Guid -eq "a0945b2b-57a2-43bd-b327-4d112a4e8bd1" -Or ` # msDS-ManagedAccountPrecededByLink Attribute
$_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000") -And ` # All Attributes
($_.InheritedObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -Or ` # msDS-DelegatedManagedServiceAccount Objects
$_.InheritedObjectType.Guid -eq "00000000-0000-0000-0000-000000000000") ` # All Objects (When Defined On A Container/OU)
))
} | ForEach-Object {
$aceToInvestigate = New-Object -TypeName System.Object
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Distinguished Name" -Value $objDN
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Canonical Name" -Value $objCanonicalName
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Object Class" -Value $objClass
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Security Principal" -Value $($_.IdentityReference.Value)
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Permissions" -Value $($_.ActiveDirectoryRights)
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Applies To" -Value $( `
If ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000" -And $_.InheritanceType -eq "None") {
"This Object Only (All Object Types)"
} ElseIf ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000" -And $_.InheritanceType -eq "All") {
"This Object And All Descendant Objects (All Object Types)"
} ElseIf ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000" -And $_.InheritanceType -eq "Descendents") {
"All Descendant Objects (All Object Types)"
} ElseIf ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -And $_.InheritanceType -eq "None") {
"This Object Only ('msDS-DelegatedManagedServiceAccount' Object Types)"
} ElseIf ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -And $_.InheritanceType -eq "All") {
"This Object And All Descendant Objects ('msDS-DelegatedManagedServiceAccount' Object Types)"
} ElseIf ($_.ActiveDirectoryRights -match "CreateChild" -And $_.ObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765" -And $_.InheritanceType -eq "Descendents") {
"All Descendant Objects 'msDS-DelegatedManagedServiceAccount' Object Types)"
} ElseIf ($_.InheritanceType -eq "None") {
"This Object Only"
} ElseIf ($_.InheritanceType -eq "All") {
"This Object And All Descendant Objects"
} ElseIf ($_.InheritanceType -eq "Descendents" -And $_.InheritedObjectType.Guid -eq "00000000-0000-0000-0000-000000000000") {
"All Descendant Objects"
} ElseIf ($_.InheritanceType -eq "Descendents" -And $_.InheritedObjectType.Guid -eq "0feb936f-47b3-49f2-9386-1dedc2c23765") {
"All Descendant 'msDS-DelegatedManagedServiceAccount' Objects"
} Else {
# PlaceHolder
} `
)
$aceToInvestigate | Add-Member -MemberType NoteProperty -Name "Attributes" -Value $( `
If ($_.ActiveDirectoryRights -match "GenericAll") {
"All Attributes"
} ElseIf ($_.ActiveDirectoryRights -match "WriteDacl" -Or $_.ActiveDirectoryRights -match "WriteOwner") {
"Not Applicable"
} ElseIf ($_.ActiveDirectoryRights -match "WriteProperty" -And $_.ObjectType.Guid -eq "2f5c138a-bd38-4016-88b4-0ec87cbb4919") {
"'msDS-DelegatedMSAState' Attribute"
} ElseIf ($_.ActiveDirectoryRights -match "WriteProperty" -And $_.ObjectType.Guid -eq "a0945b2b-57a2-43bd-b327-4d112a4e8bd1") {
"'msDS-ManagedAccountPrecededByLink' Attribute"
} ElseIf ($_.ActiveDirectoryRights -match "WriteProperty" -And $_.ObjectType.Guid -eq "00000000-0000-0000-0000-000000000000") {
"All Attributes"
} Else {
"All Attributes"
}
)
$listOfACEsToInvestigate += $aceToInvestigate
}
}
# Export To XML File
$listOfACEsToInvestigate | Export-CliXml -Path ".\$(Get-Date $datetime -Format 'yyyy-MM-dd_HH.mm.ss')_Candidate-EXPLICIT-Allow-ACEs-To-Investigate-For-dMSA-Abuse-In-Domain-$domainFQDN.xml"
# Export To Grid View
$listOfACEsToInvestigate | Sort-Object -Property "Canonical Name" | Out-GridView -Title "Candidate EXPLICIT Allow ACEs To Investigate For dMSA Abuse In Domain '$domainFQDN' ($(Get-Date $datetime -Format 'yyyy-MM-dd HH:mm:ss'))"
# Import XML Into Grid View
# Import-CliXml -Path ".\$(Get-Date $datetime -Format 'yyyy-MM-dd_HH.mm.ss')_Candidate-EXPLICIT-Allow-ACEs-To-Investigate-For-dMSA-Abuse-In-Domain-$domainFQDN.xml" | Sort-Object -Property "Canonical Name" | Out-GridView -Title "Candidate EXPLICIT Allow ACEs To Investigate For dMSA Abuse In Domain '$domainFQDN' ($(Get-Date $datetime -Format 'yyyy-MM-dd HH:mm:ss'))"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment