CertificateEnrollment
Summary
Description
Identification
PowerShell
function Find-CertificateEnrollment {
[CmdletBinding()]
param ( [string]$Target = $null,[string]$SearchBase = $null,[string]$OutputPath = "CertificateEnrollment.csv", [switch]$ExcludeAdmins = $false)
Import-Module ActiveDirectory -ErrorAction Stop
Write-Host "Gathering Active Directory Certificate Templates and inspecting ACLs for explicit 'Certificate Enrollment' permissions..."
# Access control type (Allow)
$AccessControlType = [System.Security.AccessControl.AccessControlType]::Allow;
# Active Directory Rights of Access Control Entry (ExtendedRight)
$ActiveDirectoryRights = [System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight;
# GUID of Certificate Enrollment permission
$CertificateEnrollmentGuid = "0e10c968-78fb-11d2-90d4-00c04f79dc55";
$ExcludedSIDs = @()
if ($ExcludeAdmins) {
$ExcludedSIDs += (New-Object System.Security.Principal.NTAccount "NT AUTHORITY\SYSTEM").Translate([System.Security.Principal.SecurityIdentifier]), (New-Object System.Security.Principal.NTAccount "NT AUTHORITY\SELF").Translate([System.Security.Principal.SecurityIdentifier]), (New-Object System.Security.Principal.NTAccount "BUILTIN\Account Operators").Translate([System.Security.Principal.SecurityIdentifier]), (New-Object System.Security.Principal.NTAccount "BUILTIN\Administrators").Translate([System.Security.Principal.SecurityIdentifier]), (New-Object System.Security.Principal.NTAccount "NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS").Translate([System.Security.Principal.SecurityIdentifier])
try {
$ExcludedSIDs += (Get-ADGroup -Identity "Domain Admins").SID; $ExcludedSIDs += (Get-ADGroup -Identity "Enterprise Admins").SID
$ExcludedSIDs += (Get-ADGroup -Identity "Schema Admins").SID; $ExcludedSIDs += (Get-ADGroup -Identity "Cert Publishers").SID
$ExcludedSIDs += (Get-ADGroup -Identity "Group Policy Creator Owners").SID ;$ExcludedSIDs += (Get-ADGroup -Identity "Domain Controllers").SID
$ExcludedSIDs += (Get-ADGroup -Identity "Key Admins").SID ;$ExcludedSIDs += (Get-ADGroup -Identity "Enterprise Key Admins").SID
$ExcludedSIDs += (Get-ADGroup -Identity "DnsAdmins").SID; $ExcludedSIDs += (Get-ADGroup -Identity "RAS and IAS Servers").SID
}
catch { Write-Warning "Could not resolve one or more default domain admin groups (e.g., Domain Admins, Enterprise Admins, Schema Admins). They might not be filtered from results." }
}
$foundAcls = @()
$objectsToScan = @()
try {
if ($Target) {
Write-Host "Searching for permissions on specific object: '$Target'."
$specificObject = Get-ADObject -Identity $Target -Properties nTSecurityDescriptor -ErrorAction Stop
if ($specificObject) {
$objectsToScan += $specificObject
} else {
Write-Output "Object '$Target' not found."
return
}
} else {
$configNC = (Get-ADRootDSE).ConfigurationNamingContext
$adObjectParams = @{
Filter = "ObjectClass -eq 'pKICertificateTemplate'"
Properties = "nTSecurityDescriptor"
ErrorAction = "Stop"
}
if ($SearchBase) {
$adObjectParams.Add("SearchBase", $SearchBase)
Write-Host "Searching for certificate templates within '$SearchBase'."
} else {
$adObjectParams.Add("SearchBase", $configNC)
Write-Host "Searching for all certificate templates in the Configuration Naming Context."
}
$objectsToScan = Get-ADObject @adObjectParams
}
if (-not $objectsToScan) {
Write-Output "No Active Directory Certificate Templates found matching the criteria."
return
}
foreach ($obj in $objectsToScan) {
$ObjectDistinguishedName = $obj.DistinguishedName;
try {
$acl = Get-Acl -Path "AD:$ObjectDistinguishedName"
foreach ($ace in $acl.Access) {
$isExcluded = $false
if ($ExcludeAdmins) {
try {
if ($ExcludedSIDs -contains $ace.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier])) {
$isExcluded = $true
}
}
catch {
Write-Warning "Could not translate SID for exclusion check: $($ace.IdentityReference.Value). Error: $($_.Exception.Message)"
}
}
if ($ace.AccessControlType -eq $AccessControlType -and
($ace.ActiveDirectoryRights -band $ActiveDirectoryRights) -and # Use -band for bitwise comparison
($ace.ObjectType -eq $CertificateEnrollmentGuid) -and
-not $ace.IsInherited -and
-not $isExcluded) { # Apply exclusion filter
# Add the found entry to the results array
$foundAcls += [PSCustomObject]@{
'Vulnerable Template' = $ObjectDistinguishedName
'Internal Threat' = $ace.IdentityReference.Value # Get the string representation
}
}
}
}
catch { Write-Warning "Could not retrieve ACL for '$ObjectDistinguishedName': $($_.Exception.Message)" }
}
}
catch {
Write-Error "Failed to retrieve Active Directory Certificate Templates: $($_.Exception.Message)"
return
}
if ($foundAcls.Count -gt 0) {
$exclusionMessage = if ($ExcludeAdmins) { " (excluding default admin groups and built-in accounts)" } else { "" }
Write-Host "Found $($foundAcls.Count) Active Directory certificate template(s) with explicit 'Certificate Enrollment' permissions$exclusionMessage."
try {
$foundAcls | Sort-Object -Unique 'Vulnerable Template', 'Internal Threat' | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Output "Results exported successfully to '$OutputPath'"
}
catch {
Write-Error "Failed to export results to CSV file '$OutputPath': $($_.Exception.Message)"
}
} else {
$exclusionMessage = if ($ExcludeAdmins) { " (excluding default admin groups and built-in accounts)" } else { "" }
Write-Output "No Active Directory certificate template(s) found with explicit 'Certificate Enrollment' permissions$exclusionMessage."
}
}Certification Authority (GUI)

Exploitation
Windows
Linux

Mitigation

Detection
Event ID
Description
Fields / Attributes
References
References
Last updated
Was this helpful?