Private/Set/Set-AuthorizedSignatureNotRequired.ps1
|
function Set-AuthorizedSignatureNotRequired { <# .SYNOPSIS Adds an AuthorizedSignatureNotRequired property to AD CS certificate template objects. .DESCRIPTION Examines the msPKI-RA-Signature attribute of Active Directory Certificate Services certificate template objects to determine if authorized signatures are NOT required for enrollment. The function checks the msPKI-RA-Signature attribute value. When this value is 0 or absent, certificate requests based on this template do NOT require authorized signatures (from a Registration Authority or authorized enrollment agent) before the certificate is issued. Authorized signature requirements are a strong security control that helps prevent abuse of certificate templates. When NOT required, certificates can be issued without authorized signatures, providing a potential attack vector for unauthorized enrollment. Templates without authorized signature requirements combined with other risky settings (like allowing SANs or dangerous enrollees) can lead to privilege escalation vulnerabilities. The function adds a boolean AuthorizedSignatureNotRequired property to each input object where TRUE indicates vulnerability (authorized signatures are NOT required). .PARAMETER AdcsObject One or more DirectoryEntry objects representing AD CS certificate templates. These objects must contain the msPKI-RA-Signature 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 AuthorizedSignatureNotRequired boolean property. TRUE = authorized signatures are NOT required (vulnerable). .EXAMPLE $templates = Get-AdcsObject -RootDSE $rootDSE | Where-Object { $_.objectClass -contains 'pKICertificateTemplate' } $templates | Set-AuthorizedSignatureNotRequired Processes all certificate templates and adds the AuthorizedSignatureNotRequired property to each. .EXAMPLE Get-AdcsObject -RootDSE $rootDSE | Set-AuthorizedSignatureNotRequired | Where-Object { $_.AuthorizedSignatureNotRequired } Retrieves all AD CS objects, adds AuthorizedSignatureNotRequired property, and filters to only vulnerable templates. .EXAMPLE $template = Get-AdcsObject -RootDSE $rootDSE | Where-Object Name -eq 'WebServer' $template | Set-AuthorizedSignatureNotRequired if ($template.AuthorizedSignatureNotRequired) { Write-Host "Template does not require authorized signatures - potential security risk" } Checks a specific template for authorized signature vulnerability. .NOTES The msPKI-RA-Signature attribute specifies the number of authorized signatures required: - 0 or absent: No authorized signatures required - 1 or greater: Number of authorized signatures required When authorized signatures are NOT required, users can obtain certificates directly upon enrollment. Combined with other misconfigurations (like allowing SANs or overly permissive enrollees), this can enable privilege escalation attacks. Templates requiring authorized signatures provide a strong defense-in-depth control by ensuring that only authorized principals can approve certificate issuance. .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 require authorized signatures for enrollment..." } 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" $authorizedSignatureNotRequired = $true # Check if the msPKI-RA-Signature attribute exists and is >= 1 if ($_.Properties.'msPKI-RA-Signature'.Count -gt 0) { [int]$raSignature = $_.'msPKI-RA-Signature'[0] Write-Verbose "msPKI-RA-Signature value: $raSignature" # REVERSED LOGIC: Property is true when signature is NOT required (vulnerable) if ($raSignature -ge 1) { $authorizedSignatureNotRequired = $false Write-Verbose "Authorized signature is required ($raSignature signature(s) needed) - NOT vulnerable" } else { Write-Verbose "Authorized signature is NOT required (value is 0) - VULNERABLE" } } else { Write-Verbose "msPKI-RA-Signature attribute not found on object - assuming NOT required (vulnerable)" } # Update the AdcsObjectStore with the AuthorizedSignatureNotRequired property $dn = $_.Properties.distinguishedName[0] if ($script:AdcsObjectStore.ContainsKey($dn)) { $script:AdcsObjectStore[$dn] | Add-Member -NotePropertyName AuthorizedSignatureNotRequired -NotePropertyValue $authorizedSignatureNotRequired -Force Write-Verbose "Updated AD CS Object Store for $dn with AuthorizedSignatureNotRequired = $authorizedSignatureNotRequired" } # Also add to the pipeline object for backward compatibility $_ | Add-Member -NotePropertyName AuthorizedSignatureNotRequired -NotePropertyValue $authorizedSignatureNotRequired -Force # Return the modified object $_ } catch { $errorRecord = [System.Management.Automation.ErrorRecord]::new( $_.Exception, 'AuthorizedSignatureProcessingFailed', [System.Management.Automation.ErrorCategory]::InvalidOperation, $_ ) $PSCmdlet.WriteError($errorRecord) # Still return the object even if processing failed $_ } } } end { Write-Verbose "Done identifying templates that require authorized signatures for enrollment." } } |