Private/Set/Set-AnyPurposeEKUExist.ps1
|
function Set-AnyPurposeEKUExist { <# .SYNOPSIS Adds an AnyPurposeEKUExist property to AD CS certificate template objects. .DESCRIPTION Examines the pKIExtendedKeyUsage attribute of Active Directory Certificate Services certificate template objects to determine if they allow any purpose usage. The function checks for the presence of the Any Purpose Extended Key Usage (EKU) OID: - 2.5.29.37.0: Any Purpose (allows certificates to be used for all purposes) Additionally, if the pKIExtendedKeyUsage attribute is not populated (empty or missing), this indicates the template allows all purposes by default, which is functionally equivalent to having the Any Purpose EKU explicitly set. This is a critical check for AD CS auditing, as templates that allow any purpose combined with other risky settings can lead to privilege escalation vulnerabilities. The function adds a boolean AnyPurposeEKUExist property to each input object indicating whether the template can be used for any purpose. .PARAMETER AdcsObject One or more DirectoryEntry objects representing AD CS certificate templates. These objects may contain the pKIExtendedKeyUsage attribute. .PARAMETER AnyPurposeEKU An array of EKU OIDs that represent any purpose usage. Default is '2.5.29.37.0' (Any Purpose). .INPUTS System.DirectoryServices.DirectoryEntry[] You can pipe certificate template DirectoryEntry objects to this function. .OUTPUTS System.DirectoryServices.DirectoryEntry[] Returns the input objects with an added AnyPurposeEKUExist boolean property. .EXAMPLE $templates = Get-AdcsObject -RootDSE $rootDSE | Where-Object { $_.objectClass -contains 'pKICertificateTemplate' } $templates | Set-AnyPurposeEKUExist Processes all certificate templates and adds the AnyPurposeEKUExist property to each. .EXAMPLE Get-AdcsObject -RootDSE $rootDSE | Set-AnyPurposeEKUExist | Where-Object AnyPurposeEKUExist Retrieves all AD CS objects, adds AnyPurposeEKUExist property, and filters to only any-purpose templates. .EXAMPLE $template = Get-AdcsObject -RootDSE $rootDSE | Where-Object Name -eq 'WebServer' $template | Set-AnyPurposeEKUExist if ($template.AnyPurposeEKUExist) { Write-Host "Template allows any purpose usage" } Checks a specific template for any purpose capability. .NOTES The Any Purpose EKU (2.5.29.37.0) is a wildcard that permits certificates to be used for any purpose including authentication, code signing, encryption, etc. Templates with empty pKIExtendedKeyUsage are treated as any purpose because AD CS interprets missing EKU restrictions as allowing all purposes. This is considered high-risk when combined with other misconfigurations like allowing SAN specification or having weak enrollment permissions. .LINK https://posts.specterops.io/certified-pre-owned-d95910965cd2 .LINK https://learn.microsoft.com/en-us/windows/win32/seccrypto/extended-key-usage #> [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.DirectoryServices.DirectoryEntry[]]$AdcsObject, [Parameter()] [string[]]$AnyPurposeEKU = @( '2.5.29.37.0' ) ) #requires -Version 5.1 begin { Write-Verbose "Identifying templates that create Any Purpose/Certification Authority certificates..." } process { $AdcsObject | Where-Object SchemaClassName -eq pKICertificateTemplate | ForEach-Object { try { $objectName = if ($_.Properties.displayName.Count -gt 0) { $_.Properties.displayName[0] } elseif ($_.Properties.name.Count -gt 0) { $_.Properties.name[0] } else { $_.Properties.distinguishedName[0] } Write-Verbose "Processing template: $objectName" $anyPurposeEKUExist = $false # Check if pKIExtendedKeyUsage attribute exists and has values if ($_.Properties.pKIExtendedKeyUsage.Count -gt 0) { $ekuList = $_.Properties.pKIExtendedKeyUsage Write-Verbose "pKIExtendedKeyUsage contains $($ekuList.Count) EKU(s): $($ekuList -join ', ')" # Check if any of the Any Purpose EKUs are present foreach ($eku in $ekuList) { if ($eku -in $AnyPurposeEKU) { $anyPurposeEKUExist = $true Write-Verbose "Any Purpose EKU found: $eku" break # No need to check remaining EKUs } } if (-not $anyPurposeEKUExist) { Write-Verbose "No Any Purpose EKUs found in template" } } else { $anyPurposeEKUExist = $true Write-Verbose "pKIExtendedKeyUsage is empty. Template can be used for Any Purpose." } # Update the AdcsObjectStore with the AnyPurposeEKUExist property $dn = $_.Properties.distinguishedName[0] if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn] | Add-Member -NotePropertyName AnyPurposeEKUExist -NotePropertyValue $anyPurposeEKUExist -Force Write-Verbose "Updated AD CS Object Store for $dn with AnyPurposeEKUExist = $anyPurposeEKUExist" } # Also add to the pipeline object for backward compatibility $_ | Add-Member -NotePropertyName AnyPurposeEKUExist -NotePropertyValue $anyPurposeEKUExist -Force # Return the modified object $_ } catch { $errorRecord = [System.Management.Automation.ErrorRecord]::new( $_.Exception, 'AnyPurposeEKUProcessingFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $_ ) $PSCmdlet.WriteError($errorRecord) # Still return the object even if processing failed $_ } } } end { Write-Verbose "Done identifying templates that create Any Purpose/Certification Authority certificates." } } |