Private/Set/Set-SANAllowed.ps1
|
function Set-SANAllowed { <# .SYNOPSIS Adds a SANAllowed property to AD CS certificate template objects. .DESCRIPTION Examines the msPKI-Certificate-Name-Flag attribute of Active Directory Certificate Services certificate template objects to determine if Subject Alternative Names (SANs) are allowed. The function checks bit 1 (0x00000001) of the msPKI-Certificate-Name-Flag attribute. When this bit is set, the certificate template allows enrollees to specify SANs in certificate requests, which can be a security risk if not properly controlled. This is a key indicator for ESC1 vulnerability detection in AD CS auditing. The function adds a boolean SANAllowed property to each input object indicating whether the template permits SANs. .PARAMETER AdcsObject One or more DirectoryEntry objects representing AD CS certificate templates. These objects must contain the msPKI-Certificate-Name-Flag attribute. .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 SANAllowed boolean property. .EXAMPLE $templates = Get-AdcsObject -RootDSE $rootDSE | Where-Object { $_.objectClass -contains 'pKICertificateTemplate' } $templates | Set-SANAllowed Processes all certificate templates and adds the SANAllowed property to each. .EXAMPLE Get-AdcsObject -RootDSE $rootDSE | Set-SANAllowed | Where-Object SANAllowed Retrieves all AD CS objects, adds SANAllowed property, and filters to only those allowing SANs. .EXAMPLE $template = Get-AdcsObject -RootDSE $rootDSE | Where-Object Name -eq 'WebServer' $template | Set-SANAllowed if ($template.SANAllowed) { Write-Host "Template allows Subject Alternative Names" } Checks a specific template for SAN permission. .NOTES The msPKI-Certificate-Name-Flag attribute uses bitwise flags: - Bit 1 (0x00000001): ENROLLEE_SUPPLIES_SUBJECT (allows SAN specification) When SAN is allowed without proper enrollment restrictions, it can lead to privilege escalation vulnerabilities (ESC1) by allowing users to request certificates for arbitrary principals. .LINK https://posts.specterops.io/certified-pre-owned-d95910965cd2 #> [CmdletBinding()] [OutputType([System.DirectoryServices.DirectoryEntry[]])] param ( [Parameter(Mandatory, ValueFromPipeline)] [System.DirectoryServices.DirectoryEntry[]]$AdcsObject ) #requires -Version 5.1 begin { Write-Verbose "Identifying templates that permit the use of a Subject Alternative Name (SAN)..." } 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" $sanAllowed = $false # Check if the msPKI-Certificate-Name-Flag attribute exists if ($_.Properties.'msPKI-Certificate-Name-Flag'.Count -gt 0) { [int]$certificateNameFlag = $_.'msPKI-Certificate-Name-Flag'[0] Write-Verbose "msPKI-Certificate-Name-Flag value: $certificateNameFlag (0x$($certificateNameFlag.ToString('X8')))" # Bit 1 (0x00000001) = ENROLLEE_SUPPLIES_SUBJECT (SAN allowed) if ($certificateNameFlag -band 1) { $sanAllowed = $true Write-Verbose "SAN is ALLOWED (bit 1 is set)" } else { Write-Verbose "SAN is NOT allowed (bit 1 is not set)" } } else { Write-Verbose "msPKI-Certificate-Name-Flag attribute not found on object" } # Update the AdcsObjectStore with the SANAllowed property $dn = $_.Properties.distinguishedName[0] if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn] | Add-Member -NotePropertyName SANAllowed -NotePropertyValue $sanAllowed -Force Write-Verbose "Updated AD CS Object Store for $dn with SANAllowed = $sanAllowed" } # Also add to the pipeline object for backward compatibility $_ | Add-Member -NotePropertyName SANAllowed -NotePropertyValue $sanAllowed -Force # Return the modified object $_ } catch { $errorRecord = [System.Management.Automation.ErrorRecord]::new( $_.Exception, 'SANFlagProcessingFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $_ ) $PSCmdlet.WriteError($errorRecord) # Still return the object even if processing failed $_ } } } end { Write-Verbose "Done identifying templates that permit the use of a SAN." } } |