Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESC11 Detections #177

Merged
merged 7 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 193 additions & 38 deletions Invoke-Locksmith.ps1

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions Private/Export-RevertScript.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
.PARAMETER ESC6
An array of ESC6 changes to be reverted.

.PARAMETER ESC11
An array of ESC11 changes to be reverted.

.EXAMPLE
Export-RevertScript -AuditingIssues $auditingIssues -ESC1 $ESC1 -ESC2 $ESC2 -ESC3 $ESC3 -ESC4 $ESC4 -ESC5 $ESC5 -ESC6 $ESC6
Export-RevertScript -AuditingIssues $auditingIssues -ESC1 $ESC1 -ESC2 $ESC2 -ESC3 $ESC3 -ESC4 $ESC4 -ESC5 $ESC5 -ESC6 $ESC6 -ESC11 $ESC11
Reverts the changes performed by Locksmith using the specified arrays of objects.
#>

Expand All @@ -43,19 +46,21 @@
[array]$ESC3,
[array]$ESC4,
[array]$ESC5,
[array]$ESC6
[array]$ESC6,
[array]$ESC11
)
begin {
$Output = 'Invoke-RevertLocksmith.ps1'
Set-Content -Path $Output -Value "<#`nScript to revert changes performed by Locksmith`nCreated $(Get-Date)`n#>" -Force
$Objects = $AuditingIssues + $ESC1 + $ESC2 + $ESC3 + $ESC4 + $ESC5 + $ESC6
$RevertScript = [System.Text.StringBuilder]::New()
[void]$RevertScript.Append("<#`nScript to revert changes performed by Locksmith`nCreated $(Get-Date)`n#>`n")
$Objects = $AuditingIssues + $ESC1 + $ESC2 + $ESC3 + $ESC4 + $ESC5 + $ESC6 + $ESC11
}
process {
if ($Objects) {
$Objects | ForEach-Object {
Add-Content -Path $Output -Value $_.Revert
Start-Sleep -Seconds 5
[void]$RevertScript.Append("$($_.Revert)`n")
}
$RevertScript.ToString() | Out-File -FilePath $Output
}
}
}
61 changes: 61 additions & 0 deletions Private/Find-ESC11.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
function Find-ESC11 {
<#
.SYNOPSIS
This script finds AD CS (Active Directory Certificate Services) objects that have the ESC11 vulnerability.

.DESCRIPTION
The script takes an array of ADCS objects as input and filters them based on objects that have the objectClass
'pKIEnrollmentService' and the InterfaceFlag set to 'No'. For each matching object, it creates a custom object with
properties representing various information about the object, such as Forest, Name, DistinguishedName, Technique,
Issue, Fix, and Revert.

.PARAMETER ADCSObjects
Specifies the array of ADCS objects to be processed. This parameter is mandatory.

.OUTPUTS
The script outputs an array of custom objects representing the matching ADCS objects and their associated information.

.EXAMPLE
$ADCSObjects = Get-ADCSObject -Target (Get-Target)
Find-ESC11 -ADCSObjects $ADCSObjects
$Results
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
$ADCSObjects
)
process {
$ADCSObjects | Where-Object {
($_.objectClass -eq 'pKIEnrollmentService') -and
($_.InterfaceFlag -ne 'Yes')
} | ForEach-Object {
[string]$CAFullName = "$($_.dNSHostName)\$($_.Name)"
$Issue = [pscustomobject]@{
Forest = $_.CanonicalName.split('/')[0]
Name = $_.Name
DistinguishedName = $_.DistinguishedName
Technique = 'ESC11'
Issue = $_.AuditFilter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checking because I haven't run and tested results yet: is $_.AuditFilter right? What should that return?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. I also updated the ESC6 logic which does the same check!

Fix = 'N/A'
Revert = 'N/A'
}
if ($_.InterfaceFlag -eq 'No') {
$Issue.Issue = 'IF_ENFORCEENCRYPTICERTREQUEST is disabled.'
$Issue.Fix = @"
certutil -config $CAFullname -setreg CA\InterfaceFlags +IF_ENFORCEENCRYPTICERTREQUEST
Invoke-Command -ComputerName `"$($_.dNSHostName)`" -ScriptBlock {
Get-Service -Name `'certsvc`' | Restart-Service -Force
}
"@
$Issue.Revert = @"
certutil -config $CAFullname -setreg CA\InterfaceFlags -IF_ENFORCEENCRYPTICERTREQUEST
Invoke-Command -ComputerName `"$($_.dNSHostName)`" -ScriptBlock {
Get-Service -Name `'certsvc`' | Restart-Service -Force
}
"@
}
$Issue
}
}
}
9 changes: 8 additions & 1 deletion Private/Format-Result.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,18 @@ function Format-Result {
ESC5 = 'ESC5 - Vulnerable Access Control - PKI Object'
ESC6 = 'ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2 Flag Enabled'
ESC8 = 'ESC8 - HTTP/S Enrollment Enabled'
ESC11 = 'ESC11 - IF_ENFORCEENCRYPTICERTREQUEST Flag Disabled'
}

if ($null -ne $Issue) {
$UniqueIssue = $Issue.Technique | Sort-Object -Unique
Write-Host "`n########## $($IssueTable[$UniqueIssue]) ##########`n"
$Title = $($IssueTable[$UniqueIssue])
Write-Host "$('-'*($($Title.ToString().Length + 10)))" -ForeGroundColor Magenta -BackgroundColor Magenta -NoNewline; Write-Host
Write-Host " " -BackgroundColor Magenta -NoNewline
Write-Host $Title -BackgroundColor Magenta -ForeGroundColor White -NoNewline
Write-Host " " -BackgroundColor Magenta -NoNewline; Write-Host
Write-Host "$('-'*($($Title.ToString().Length + 10)))" -ForeGroundColor Magenta -BackgroundColor Magenta -NoNewline; Write-Host

switch ($Mode) {
0 {
$Issue | Format-Table Technique, Name, Issue -Wrap
Expand Down
41 changes: 39 additions & 2 deletions Private/Invoke-Remediation.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ function Invoke-Remediation {
.PARAMETER ESC6
A PS Object containing all necessary information about ESC6 issues.

.PARAMETER ESC6
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/paste fix needed here for "ESC11."

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

A PS Object containing all necessary information about ESC11 issues.

.INPUTS
PS Objects

Expand All @@ -42,15 +45,16 @@ function Invoke-Remediation {
$ESC3,
$ESC4,
$ESC5,
$ESC6
$ESC6,
$ESC11
)

Write-Host "`nExecuting Mode 4 - Attempting to fix identified issues!`n" -ForegroundColor Green
Write-Host 'Creating a script (' -NoNewline
Write-Host 'Invoke-RevertLocksmith.ps1' -ForegroundColor White -NoNewline
Write-Host ") which can be used to revert all changes made by Locksmith...`n"
try {
Export-RevertScript -AuditingIssues $AuditingIssues -ESC1 $ESC1 -ESC2 $ESC2 -ESC3 $ESC3 -ESC4 $ESC4 -ESC5 $ESC5 -ESC6 $ESC6
Export-RevertScript -AuditingIssues $AuditingIssues -ESC1 $ESC1 -ESC2 $ESC2 -ESC3 $ESC3 -ESC4 $ESC4 -ESC5 $ESC5 -ESC6 $ESC6 -ESC11 $ESC11
} catch {
Write-Warning 'Creation of Invoke-RevertLocksmith.ps1 failed.'
Write-Host "Continue with this operation? [Y] Yes " -NoNewline
Expand Down Expand Up @@ -253,6 +257,39 @@ function Invoke-Remediation {
}
}

if ($ESC11) {
$ESC11 | ForEach-Object {
$FixBlock = [scriptblock]::Create($_.Fix)
Write-Host 'ISSUE:' -ForegroundColor White
Write-Host "The Certification Authority `"$($_.Name)`" has the IF_ENFORCEENCRYPTICERTREQUEST flag disabled.`n"
Write-Host 'TECHNIQUE:' -ForegroundColor White
Write-Host "$($_.Technique)`n"
Write-Host 'ACTION TO BE PERFORMED:' -ForegroundColor White
Write-Host "Locksmith will attempt to enable the IF_ENFORCEENCRYPTICERTREQUEST flag on Certifiction Authority `"$($_.Name)`".`n"
Write-Host 'COMMAND(S) TO BE RUN' -ForegroundColor White
Write-Host 'PS> ' -NoNewline
Write-Host "$($_.Fix)`n" -ForegroundColor Cyan
$WarningError = 'n'
Write-Host 'OPERATIONAL IMPACT:' -ForegroundColor White
Write-Host "WARNING: This change could cause some services to stop working.`n" -ForegroundColor Yellow
Write-Host "If you continue, Locksmith will attempt to fix this issue.`n" -ForegroundColor Yellow
Write-Host "Continue with this operation? [Y] Yes " -NoNewline
Write-Host "[N] " -ForegroundColor Yellow -NoNewline
Write-Host "No: " -NoNewLine
$WarningError = ''
$WarningError = Read-Host
if ($WarningError -like 'y') {
try {
Invoke-Command -ScriptBlock $FixBlock
} catch {
Write-Error 'Could not enable the IF_ENFORCEENCRYPTICERTREQUEST flag. Are you an Active Directory or AD CS admin?'
}
} else {
Write-Host "SKIPPED!`n" -ForegroundColor Yellow
}
}
}

Write-Host "Mode 4 Complete! There are no more issues that Locksmith can automatically resolve.`n" -ForegroundColor Green
Write-Host 'If you experience any operational impact from using Locksmith Mode 4, use ' -NoNewline
Write-Host 'Invoke-RevertLocksmith.ps1 ' -ForegroundColor White
Expand Down
63 changes: 35 additions & 28 deletions Private/Invoke-Scans.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ function Invoke-Scans {
- ESC5
- ESC6
- ESC8
- ESC11
- All
- PromptMe

.PARAMETER Scans
Specifies the type of scans to perform. Multiple scan options can be provided as an array. The default value is 'All'.
The available scan options are: 'Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC8', 'All', 'PromptMe'.
The available scan options are: 'Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC8', 'ESC11', 'All', 'PromptMe'.

.NOTES
- The script requires the following functions to be defined: Find-AuditingIssue, Find-ESC1, Find-ESC2, Find-ESC3Condition1,
Find-ESC3Condition2, Find-ESC4, Find-ESC5, Find-ESC6, Find-ESC8.
Find-ESC3Condition2, Find-ESC4, Find-ESC5, Find-ESC6, Find-ESC8, Find-ESC8.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/paste fix for "Find-ESC11" needed.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

- The script uses Out-GridView or Out-ConsoleGridView for interactive selection when the 'PromptMe' scan option is chosen.
- The script returns a hash table containing the results of the scans.

Expand All @@ -41,17 +42,17 @@ function Invoke-Scans {

[CmdletBinding()]
[OutputType([hashtable])]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Invoke-Scans', Justification='Performing multiple scans.')]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Invoke-Scans', Justification = 'Performing multiple scans.')]
param (
# Could split Scans and PromptMe into separate parameter sets.
[Parameter()]
# Could split Scans and PromptMe into separate parameter sets.
[Parameter()]
$ClientAuthEkus,
$DangerousRights,
$EnrollmentAgentEKU,
[int]$Mode,
$SafeObjectTypes,
$SafeOwners,
[ValidateSet('Auditing','ESC1','ESC2','ESC3','ESC4','ESC5','ESC6','ESC8','All','PromptMe')]
[ValidateSet('Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC8', 'ESC11', 'All', 'PromptMe')]
[array]$Scans = 'All',
$UnsafeOwners,
$UnsafeUsers,
Expand All @@ -68,12 +69,10 @@ function Invoke-Scans {

# Check for Out-GridView or Out-ConsoleGridView
if ((Get-Command Out-ConsoleGridView -ErrorAction SilentlyContinue) -and ($PSVersionTable.PSVersion.Major -ge 7)) {
[array]$Scans = ($Dictionary | Select-Object Name,Category,Subcategory | Out-ConsoleGridView -OutputMode Multiple -Title $GridViewTitle).Name | Sort-Object -Property Name
}
elseif (Get-Command -Name Out-GridView -ErrorAction SilentlyContinue) {
[array]$Scans = ($Dictionary | Select-Object Name,Category,Subcategory | Out-GridView -PassThru -Title $GridViewTitle).Name | Sort-Object -Property Name
}
else {
[array]$Scans = ($Dictionary | Select-Object Name, Category, Subcategory | Out-ConsoleGridView -OutputMode Multiple -Title $GridViewTitle).Name | Sort-Object -Property Name
} elseif (Get-Command -Name Out-GridView -ErrorAction SilentlyContinue) {
[array]$Scans = ($Dictionary | Select-Object Name, Category, Subcategory | Out-GridView -PassThru -Title $GridViewTitle).Name | Sort-Object -Property Name
} else {
# To Do: Check for admin and prompt to install features/modules or revert to 'All'.
Write-Information "Out-GridView and Out-ConsoleGridView were not found on your system. Defaulting to `'All`'."
$Scans = 'All'
Expand All @@ -99,21 +98,25 @@ function Invoke-Scans {
[array]$ESC3 += Find-ESC3Condition2 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers
}
ESC4 {
Write-Host 'Identifying AD CS template and other objects with poor access control (ESC4)...'
Write-Host 'Identifying AD CS templates with poor access control (ESC4)...'
[array]$ESC4 = Find-ESC4 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers -DangerousRights $DangerousRights -SafeOwners $SafeOwners -SafeObjectTypes $SafeObjectTypes
}
ESC5 {
Write-Host 'Identifying AD CS template and other objects with poor access control (ESC5)...'
Write-Host 'Identifying AD CS objects with poor access control (ESC5)...'
[array]$ESC5 = Find-ESC5 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers -DangerousRights $DangerousRights -SafeOwners $SafeOwners -SafeObjectTypes $SafeObjectTypes
}
ESC6 {
Write-Host 'Identifying AD CS template and other objects with poor access control (ESC6)...'
Write-Host 'Identifying Issuing CAs with EDITF_ATTRIBUTESUBJECTALTNAME2 enabled (ESC6)...'
[array]$ESC6 = Find-ESC6 -ADCSObjects $ADCSObjects
}
ESC8 {
Write-Host 'Identifying HTTP-based certificate enrollment interfaces (ESC8)...'
[array]$ESC8 = Find-ESC8 -ADCSObjects $ADCSObjects
}
ESC6 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/paste fix "ESC6" to "ESC11"

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Write-Host 'Identifying Issuing CAs with IF_ENFORCEENCRYPTICERTREQUEST disabled (ESC11)...'
[array]$ESC6 = Find-ESC6 -ADCSObjects $ADCSObjects
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/paste fix "ESC6" to "ESC11"

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

}
All {
Write-Host 'Identifying auditing issues...'
[array]$AuditingIssues = Find-AuditingIssue -ADCSObjects $ADCSObjects
Expand All @@ -124,35 +127,39 @@ function Invoke-Scans {
Write-Host 'Identifying AD CS templates with dangerous ESC3 configurations...'
[array]$ESC3 = Find-ESC3Condition1 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers
[array]$ESC3 += Find-ESC3Condition2 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers
Write-Host 'Identifying AD CS template and other objects with poor access control (ESC4)...'
Write-Host 'Identifying AD CS templates with poor access control (ESC4)...'
[array]$ESC4 = Find-ESC4 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers -DangerousRights $DangerousRights -SafeOwners $SafeOwners -SafeObjectTypes $SafeObjectTypes -Mode $Mode
Write-Host 'Identifying AD CS template and other objects with poor access control (ESC5)...'
Write-Host 'Identifying AD CS objects with poor access control (ESC5)...'
[array]$ESC5 = Find-ESC5 -ADCSObjects $ADCSObjects -SafeUsers $SafeUsers -DangerousRights $DangerousRights -SafeOwners $SafeOwners -SafeObjectTypes $SafeObjectTypes
Write-Host 'Identifying Certificate Authorities configured with dangerous flags (ESC6)...'
Write-Host 'Identifying Certificate Authorities with EDITF_ATTRIBUTESUBJECTALTNAME2 enabled v (ESC6)...'
[array]$ESC6 = Find-ESC6 -ADCSObjects $ADCSObjects
Write-Host 'Identifying HTTP-based certificate enrollment interfaces (ESC8)...'
[array]$ESC8 = Find-ESC8 -ADCSObjects $ADCSObjects
Write-Host 'Identifying Certificate Authorities with IF_ENFORCEENCRYPTICERTREQUEST disabled (ESC11)...'
[array]$ESC11 = Find-ESC11 -ADCSObjects $ADCSObjects
Write-Host
}
}

[array]$AllIssues = $AuditingIssues + $ESC1 + $ESC2 + $ESC3 + $ESC4 + $ESC5 + $ESC6 + $ESC8
[array]$AllIssues = $AuditingIssues + $ESC1 + $ESC2 + $ESC3 + $ESC4 + $ESC5 + $ESC6 + $ESC8 + $ESC11

# If these are all empty = no issues found, exit
if ((!$AuditingIssues) -and (!$ESC1) -and (!$ESC2) -and (!$ESC3) -and (!$ESC4) -and (!$ESC5) -and (!$ESC6) -and (!$ESC8) ) {
if ((!$AuditingIssues) -and (!$ESC1) -and (!$ESC2) -and (!$ESC3) -and (!$ESC4) -and (!$ESC5) -and (!$ESC6) -and (!$ESC8) -and ($ESC11) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new segment should be -and (!($ESC11) ) { but is missing the ! operator.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Write-Host "`n$(Get-Date) : No ADCS issues were found." -ForegroundColor Green
break
}

# Return a hash table of array names (keys) and arrays (values) so they can be directly referenced with other functions
Return @{
AllIssues = $AllIssues
AllIssues = $AllIssues
AuditingIssues = $AuditingIssues
ESC1 = $ESC1
ESC2 = $ESC2
ESC3 = $ESC3
ESC4 = $ESC4
ESC5 = $ESC5
ESC6 = $ESC6
ESC8 = $ESC8
ESC1 = $ESC1
ESC2 = $ESC2
ESC3 = $ESC3
ESC4 = $ESC4
ESC5 = $ESC5
ESC6 = $ESC6
ESC8 = $ESC8
ESC11 = $ESC11
}
}
18 changes: 9 additions & 9 deletions Private/New-Dictionary.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,15 @@ function New-Dictionary {
# FixIt = {Write-Output 'Add code to fix the vulnerable configuration.'}
# ReferenceUrls = ''
# },
# [VulnerableConfigurationItem]@{
# Name = 'ESC11'
# Category = 'Escalation Path'
# Subcategory = ''
# Summary = ''
# FindIt = {Find-ESC11}
# FixIt = {Write-Output 'Add code to fix the vulnerable configuration.'}
# ReferenceUrls = ''
# },
[VulnerableConfigurationItem]@{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes to the dictionary should include a bump in the dictionary version attribute on line 24, which is currently: static [string] $Version = '2023.10.01.000'.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Name = 'ESC11'
Category = 'Escalation Path'
Subcategory = 'IF_ENFORCEENCRYPTICERTREQUEST'
Summary = ''
FindIt = {Find-ESC11}
FixIt = {Write-Output 'Add code to fix the vulnerable configuration.'}
ReferenceUrls = 'https://blog.compass-security.com/2022/11/relaying-to-ad-certificate-services-over-rpc/'
},
[VulnerableConfigurationItem]@{
Name = 'Auditing'
Category = 'Server Configuration'
Expand Down
Loading
Loading