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 {
    }
}