Private/Test/Test-IsEnrollmentAce.ps1
|
function Test-IsEnrollmentAce { <# .SYNOPSIS Tests if an Active Directory access control entry grants certificate enrollment permissions. .DESCRIPTION Examines Active Directory access control entries (ACEs) on certificate template objects to determine if they grant enrollment permissions to a security principal. The function checks for the presence of enrollment-related permissions: - ExtendedRight: Grants specific extended rights (including Certificate-Enrollment) - GenericAll: Grants all permissions including enrollment The function also validates that the ObjectType matches the Certificate-Enrollment extended right GUID (0e10c968-78fb-11d2-90d4-00c04f79dc55) or the all-zeros GUID (00000000-0000-0000-0000-000000000000) which applies to all object types. Only Allow ACEs are considered; Deny ACEs always return false even if they have enrollment rights specified. This is critical for ESC1 vulnerability detection in AD CS auditing, as overly permissive enrollment permissions combined with other risky settings can lead to privilege escalation. .PARAMETER Ace One or more ActiveDirectoryAccessRule objects to test for enrollment permissions. Typically obtained from a certificate template's ObjectSecurity.Access property. .INPUTS System.DirectoryServices.ActiveDirectoryAccessRule[] You can pipe access control entries to this function. .OUTPUTS System.Boolean Returns $true if the ACE grants enrollment permissions, $false otherwise. When multiple ACEs are provided, returns one boolean per ACE. .EXAMPLE $template = Get-AdcsObject | Where-Object Name -eq 'WebServer' $template.ObjectSecurity.Access | Test-IsEnrollmentAce Tests all ACEs on the WebServer template for enrollment permissions. .EXAMPLE $aces = $template.ObjectSecurity.Access | Where-Object IdentityReference -like '*Domain Users*' $aces | Test-IsEnrollmentAce Tests only Domain Users ACEs for enrollment permissions. .EXAMPLE $canEnroll = $template.ObjectSecurity.Access[0] | Test-IsEnrollmentAce if ($canEnroll) { Write-Host "First ACE grants enrollment permission" } Tests a single ACE and uses the result in conditional logic. .NOTES Certificate-Enrollment Extended Right GUID: 0e10c968-78fb-11d2-90d4-00c04f79dc55 .LINK https://posts.specterops.io/certified-pre-owned-d95910965cd2 .LINK https://learn.microsoft.com/en-us/windows/win32/adschema/r-certificate-enrollment #> [CmdletBinding()] [OutputType([bool])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.DirectoryServices.ActiveDirectoryAccessRule[]]$Ace ) #requires -Version 5.1 begin { $enrollmentRight = 'ExtendedRight|GenericAll' $enrollmentObjectType = '0e10c968-78fb-11d2-90d4-00c04f79dc55|00000000-0000-0000-0000-000000000000' } process { $Ace | ForEach-Object { Write-Verbose "Testing if $($_.IdentityReference) can enroll in this certificate..." $canEnroll = $false $isAllow = $_.AccessControlType -eq 'Allow' $hasRight = $_.ActiveDirectoryRights -match $enrollmentRight $objectType = $_.ObjectType -match $enrollmentObjectType if ($isAllow -and $hasRight -and $objectType) { $canEnroll = $true } $canEnroll Write-Verbose "Done testing if $($_.IdentityReference) can enroll in this certificate." } } end { } } |