Analyzers/Test-Esc15.ps1
|
function Test-Esc15 { <# .SYNOPSIS ESC15 - EKUwu / arbitrary Application Policies on V1 templates (CVE-2024-49019). .DESCRIPTION Read-only analyzer. Any schema-version-1 certificate template that a low-priv principal may enroll (and that is published on a CA) is vulnerable: the attacker injects arbitrary Application Policies (e.g. Client Authentication, Certificate Request Agent) into the request, so the template's own EkuList is IRRELEVANT. Enrollee-supplies-subject raises exploitability; manager approval or RA signatures lower it. .PARAMETER Context AssessmentContext pscustomobject. .PARAMETER ExtraLowPrivSid Additional SID strings to treat as low-privileged. .OUTPUTS Finding[] #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [pscustomobject] $Context, [Parameter(Mandatory = $false)] [string[]] $ExtraLowPrivSid = @() ) $reference = 'https://www.tenable.com/security/research/tra-2024-49 (CVE-2024-49019 EKUwu)' $findings = @() $extra = @() if ($ExtraLowPrivSid) { $extra += $ExtraLowPrivSid } if ($Context.ExtraLowPrivSid) { $extra += $Context.ExtraLowPrivSid } if ($null -eq $Context.Templates) { return @([pscustomobject]@{ Id = 'ESC15'; Title = 'ESC15 template data unavailable'; Severity = 'Critical'; Status = 'ManualReview'; AffectedObject = 'N/A'; Evidence = [pscustomobject]@{ Reason = 'Context.Templates was null; no certificate template data collected.' }; Principals = @(); Exploitability = 'Theoretical'; RiskScore = 0; Remediation = 'Re-run template collection.'; Reference = $reference }) } foreach ($tmpl in $Context.Templates) { if ($null -eq $tmpl.SchemaVersion -or [int]$tmpl.SchemaVersion -ne 1) { continue } $lowPrivEnrollers = @() foreach ($ace in @($tmpl.EnrollPrincipals)) { if ($null -eq $ace) { continue } if ($ace.AceType -ne 'Allow') { continue } $isEnroll = ($ace.Rights -contains 'Enroll') -or ($ace.Rights -contains 'GenericAll') if (-not $isEnroll) { continue } $isLow = $false if ($ace.IsLowPriv) { $isLow = $true } else { $isLow = Test-EscLowPrivPrincipal -Sid $ace.PrincipalSid -ExtraLowPrivSid $extra } if ($isLow) { $lowPrivEnrollers += $ace } } if ($lowPrivEnrollers.Count -eq 0) { continue } $published = @($tmpl.PublishedOnCAs) $isPublished = ($published.Count -gt 0) $principals = @($lowPrivEnrollers | ForEach-Object { if ($_.PrincipalName) { $_.PrincipalName } else { $_.PrincipalSid } } | Select-Object -Unique) $ess = $false if ($null -ne $tmpl.EnrolleeSuppliesSubject) { $ess = [bool]$tmpl.EnrolleeSuppliesSubject } elseif ($null -ne $tmpl.NameFlag) { $ess = (([int]$tmpl.NameFlag) -band 0x1) -ne 0 } $approval = [bool]$tmpl.ManagerApprovalRequired $raReq = 0 if ($null -ne $tmpl.RaSignaturesRequired) { $raReq = [int]$tmpl.RaSignaturesRequired } if ($ess) { $exploit = 'High' } else { $exploit = 'Medium' } if ($approval -or $raReq -gt 0) { $exploit = 'Low' } if ($isPublished) { $status = 'Vulnerable' } else { $status = 'Potential' if ($exploit -eq 'High') { $exploit = 'Medium' } } $findings += [pscustomobject]@{ Id = 'ESC15' Title = "V1 template '$($tmpl.Name)' allows Application Policy injection (ESC15/EKUwu)" Severity = 'Critical' Status = $status AffectedObject = $tmpl.Name Evidence = [pscustomobject]@{ Template = $tmpl.Name SchemaVersion = 1 PublishedOnCAs = $published EnrolleeSuppliesSubject = $ess ManagerApprovalRequired = $approval RaSignaturesRequired = $raReq LowPrivEnrollers = $principals Note = 'EkuList is irrelevant - attacker supplies Application Policies (e.g. Client Auth / Enrollment Agent) in the CSR. CA patch state cannot be confirmed remotely; unpatched CAs are exploitable.' CaPatchCaveat = 'If the CA is patched for CVE-2024-49019 the injection is blocked; verify KB patch level on the issuing CA.' } Principals = $principals Exploitability = $exploit RiskScore = 0 Remediation = 'Patch issuing CAs for CVE-2024-49019, retire/replace schema V1 templates, and restrict enrollment to trusted principals.' Reference = $reference } } if ($findings.Count -eq 0) { return @([pscustomobject]@{ Id = 'ESC15'; Title = 'No ESC15 (EKUwu) V1 enrollable templates found'; Severity = 'Info'; Status = 'NotVulnerable'; AffectedObject = 'All templates'; Evidence = [pscustomobject]@{ TemplatesChecked = @($Context.Templates).Count }; Principals = @(); Exploitability = 'Theoretical'; RiskScore = 0; Remediation = 'None required.'; Reference = $reference }) } return $findings } |