Analyzers/Test-Esc16.ps1
|
function Test-Esc16 { <# .SYNOPSIS ESC16 - szOID_NTDS_CA_SECURITY_EXT globally disabled on a CA. .DESCRIPTION Read-only analyzer over $Context.CaConfigs. A CA is vulnerable when its DisableExtensionList (policy\DisableExtensionList) contains 1.3.6.1.4.1.311.25.2 (szOID_NTDS_CA_SECURITY_EXT): the SID security extension is then omitted from EVERY certificate the CA issues, CA-wide - the same primitive as ESC9 but not scoped to a single template. Contrast with ESC9 (per-template CT_FLAG_NO_SECURITY_EXTENSION). Exploitability depends on DC strong-binding enforcement (< 2 required), cross-referenced from $Context.DcMappings. Unreachable CAs -> ManualReview. .PARAMETER Context AssessmentContext pscustomobject. .PARAMETER ExtraLowPrivSid Unused for ESC16 (kept for signature uniformity). .OUTPUTS Finding[] #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject] $Context, [Parameter(Mandatory = $false)] [string[]] $ExtraLowPrivSid = @() ) $reference = 'https://github.com/ly4k/Certipy (ESC16 - security extension disabled)' $secExtOid = '1.3.6.1.4.1.311.25.2' $findings = @() if ($null -eq $Context.CaConfigs -or @($Context.CaConfigs).Count -eq 0) { return @([pscustomobject]@{ Id = 'ESC16'; Title = 'ESC16 CA configuration data unavailable'; Severity = 'High'; Status = 'ManualReview'; AffectedObject = 'Certificate Authorities'; Evidence = [pscustomobject]@{ Reason = 'Context.CaConfigs was null/empty; DisableExtensionList not collected.' }; Principals = @(); Exploitability = 'Theoretical'; RiskScore = 0; Remediation = 'Collect policy\DisableExtensionList via certutil -getreg policy\DisableExtensionList.'; Reference = $reference }) } $weakDcs = @() $dcDataPresent = $false if ($Context.DcMappings) { foreach ($dc in $Context.DcMappings) { if ($dc.Reachable -eq $false) { continue } $dcDataPresent = $true if ($null -ne $dc.StrongCertificateBindingEnforcement -and [int]$dc.StrongCertificateBindingEnforcement -lt 2) { $weakDcs += $dc.DomainController } } } $anyReachable = $false foreach ($ca in $Context.CaConfigs) { $caName = $ca.Name if ($ca.Reachable -eq $false) { $findings += [pscustomobject]@{ Id = 'ESC16'; Title = "CA '$caName' unreachable - DisableExtensionList unknown"; Severity = 'High'; Status = 'ManualReview'; AffectedObject = $caName; Evidence = [pscustomobject]@{ Ca = $caName; Reachable = $false; Reason = 'certutil / registry read failed.' }; Principals = @(); Exploitability = 'Theoretical'; RiskScore = 0; Remediation = 'Manually verify policy\DisableExtensionList on this CA.'; Reference = $reference } continue } $anyReachable = $true $disList = @() if ($null -ne $ca.DisableExtensionList) { $disList = @($ca.DisableExtensionList | ForEach-Object { if ($_) { ([string]$_).Trim() } }) } $disabled = ($disList -contains $secExtOid) if (-not $disabled) { continue } if ($weakDcs.Count -gt 0) { $exploit = 'High' $dcNote = "Weak-binding DC(s) present (StrongCertificateBindingEnforcement < 2): $($weakDcs -join ', ')" } elseif ($dcDataPresent) { $exploit = 'Low' $dcNote = 'All reachable DCs enforce StrongCertificateBindingEnforcement >= 2; exploitation blocked unless a weak DC exists.' } else { $exploit = 'Medium' $dcNote = 'DC binding enforcement unknown (no reachable DcMappings); verify StrongCertificateBindingEnforcement < 2 on a DC.' } $findings += [pscustomobject]@{ Id = 'ESC16' Title = "CA '$caName' disables the SID security extension CA-wide (ESC16)" Severity = 'High' Status = 'Vulnerable' AffectedObject = $caName Evidence = [pscustomobject]@{ Ca = $caName DnsHostName = $ca.DnsHostName DisableExtensionList = $disList DisabledOid = $secExtOid Scope = 'CA-wide - EVERY certificate issued by this CA omits szOID_NTDS_CA_SECURITY_EXT (SID binding).' DcContext = $dcNote ContrastWithEsc9 = 'ESC9 is per-template (CT_FLAG_NO_SECURITY_EXTENSION); ESC16 is this per-CA DisableExtensionList setting. Any client-auth-capable template on this CA becomes an ESC9-style impersonation vector.' } Principals = @() Exploitability = $exploit RiskScore = 0 Remediation = 'Remove 1.3.6.1.4.1.311.25.2 from policy\DisableExtensionList (certutil -setreg), restart CertSvc, and set StrongCertificateBindingEnforcement=2 on all DCs.' Reference = $reference } } if ($findings.Count -eq 0) { $status = 'NotVulnerable'; $sev = 'Info' if (-not $anyReachable) { $status = 'ManualReview'; $sev = 'High' } return @([pscustomobject]@{ Id = 'ESC16'; Title = 'No CA globally disables the SID security extension (no ESC16)'; Severity = $sev; Status = $status; AffectedObject = 'Certificate Authorities'; Evidence = [pscustomobject]@{ CasChecked = @($Context.CaConfigs).Count; AnyReachable = $anyReachable }; Principals = @(); Exploitability = 'Theoretical'; RiskScore = 0; Remediation = 'None required.'; Reference = $reference }) } return $findings } |