Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Build/Build-Module.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Build-Module -ModuleName 'Locksmith' {

# The scans to run. Defaults to 'All'.
[Parameter()]
[ValidateSet('Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC8', 'ESC11', 'ESC13', 'ESC15', 'EKUwu', 'All', 'PromptMe')]
[ValidateSet('Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC7', 'ESC8', 'ESC9', 'ESC11', 'ESC13', 'ESC15', 'EKUwu', 'ESC16', 'All', 'PromptMe')]
[array]$Scans = 'All'
)
}
Expand Down
835 changes: 699 additions & 136 deletions Invoke-Locksmith.ps1

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Locksmith.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
FunctionsToExport = 'Invoke-Locksmith'
GUID = 'b1325b42-8dc4-4f17-aa1f-dcb5984ca14a'
HelpInfoURI = 'https://raw.githubusercontent.com/jakehildreth/Locksmith/main/en-US/'
ModuleVersion = '2025.4.20'
ModuleVersion = '2025.5.26'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
Expand Down
8 changes: 5 additions & 3 deletions Private/Find-ESC1.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@ Get-ADObject `$Object | Set-ADObject -Replace @{'msPKI-Enrollment-Flag' = 0}
Technique = 'ESC1'
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC1Remediation -Issue $Issue
}
if ($SkipRisk -eq $false) {
Set-RiskRating -ADCSObjects $ADCSObjects -Issue $Issue -SafeUsers $SafeUsers -UnsafeUsers $UnsafeUsers
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC1Remediation -Issue $Issue
}

$Issue
}
}
Expand Down
75 changes: 75 additions & 0 deletions Private/Find-ESC16.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
function Find-ESC16 {
<#
.SYNOPSIS
This script finds Active Directory Certificate Services (AD CS) Certification Authorities (CA) that have the ESC16 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 szOID_NTDS_CA_SECURITY_EXT disabled. 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 AD CS 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.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[Microsoft.ActiveDirectory.Management.ADEntity[]]$ADCSObjects,
[Parameter(Mandatory)]
[string]$UnsafeUsers,
[switch]$SkipRisk
)
process {
$ADCSObjects | Where-Object {
($_.objectClass -eq 'pKIEnrollmentService') -and
($_.DisableExtensionList -ne 'No')
} | ForEach-Object {
$Issue = [pscustomobject]@{
Forest = $_.CanonicalName.split('/')[0]
Name = $_.Name
DistinguishedName = $_.DistinguishedName
Issue = $_.DisableExtensionList
Fix = 'N/A'
Revert = 'N/A'
Technique = 'ESC16'
}
if ($_.DisableExtensionList -eq 'Yes') {
$Issue.Issue = @"
The Certification Authority (CA) $($_.CAFullName) has the szOID_NTDS_CA_SECURITY_EXT security extension disabled. When
this extension is disabled, every certificate issued by this CA will be unable to to reliably map a certificate to a
user or computer account's SID for authentication.

More info:
- https://github.com/ly4k/Certipy/wiki/06-%E2%80%90-Privilege-Escalation#esc16-security-extension-disabled-on-ca-globally

"@
$Issue.Fix = @"
# Enable the flag
# TODO

# Restart the Certificate Authority service
Invoke-Command -ComputerName '$($_.dNSHostName)' -ScriptBlock {
Get-Service -Name certsvc | Restart-Service -Force
}
"@
$Issue.Revert = @"
# Disable the flag
TODO

# Restart the Certificate Authority service
Invoke-Command -ComputerName '$($_.dNSHostName)' -ScriptBlock {
Get-Service -Name certsvc | Restart-Service -Force
}
"@
}
if ($SkipRisk -eq $false) {
Set-RiskRating -ADCSObjects $ADCSObjects -Issue $Issue -SafeUsers $SafeUsers -UnsafeUsers $UnsafeUsers
}
$Issue
}
}
}
2 changes: 1 addition & 1 deletion Private/Find-ESC3C1.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
$($entry.IdentityReference) can use this template to request an Enrollment Agent
certificate without Manager Approval.

The resulting certificate can be used to enroll in any template that requires
The resulting certificate can be used to enroll in any template that allows
an Enrollment Agent to submit the request.

More info:
Expand Down
8 changes: 5 additions & 3 deletions Private/Find-ESC4.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ Set-Acl -Path 'AD:$($_.DistinguishedName)' -AclObject `$ACL
Technique = 'ESC4'
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC4Remediation -Issue $Issue
}
if ($SkipRisk -eq $false) {
Set-RiskRating -ADCSObjects $ADCSObjects -Issue $Issue -SafeUsers $SafeUsers -UnsafeUsers $UnsafeUsers
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC4Remediation -Issue $Issue
}

$Issue
}
}
Expand Down
1 change: 1 addition & 0 deletions Private/Find-ESC6.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
$Issue = [pscustomobject]@{
Forest = $_.CanonicalName.split('/')[0]
Name = $_.Name
CAFullname = $CAFullName
DistinguishedName = $_.DistinguishedName
Issue = $_.SANFlag
Fix = 'N/A'
Expand Down
114 changes: 114 additions & 0 deletions Private/Find-ESC7.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
function Find-ESC7 {
<#
.SYNOPSIS
This script finds Active Directory Certificate Services (AD CS) Certificate Authorities (CA) that have the ESC7 vulnerability.

.DESCRIPTION
The script takes an array of AD CS objects as input and filters them based on objects that have the objectClass
'pKIEnrollmentService'. If the CA objects have non-standard/unsafe principals as administrators or managers, an issue is created.

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

.PARAMETER UnsafeUsers
Principals that should never be granted control of a CA.

.PARAMETER SafeUsers
Principals that are generally recognized as safe to control a CA.

.PARAMETER SkipRisk
Switch used when processing second-order risks.

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

#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[Microsoft.ActiveDirectory.Management.ADEntity[]]$ADCSObjects,
[Parameter(Mandatory)]
[string]$UnsafeUsers,
[Parameter(Mandatory)]
[string]$SafeUsers,
[switch]$SkipRisk
)
process {
Write-Output $ADCSObjects -PipelineVariable object | Where-Object {
($object.objectClass -eq 'pKIEnrollmentService') -and $object.CAHostDistinguishedName -and
( ($object.CAAdministrator) -or ($object.CertificateManager) )
} | ForEach-Object {
Write-Output $object.CAAdministrator -PipelineVariable admin | ForEach-Object {
$SID = Convert-IdentityReferenceToSid -Object $admin
if ($SID -notmatch $SafeUsers) {
$Issue = [pscustomobject]@{
Forest = $object.CanonicalName.split('/')[0]
Name = $object.Name
DistinguishedName = $object.DistinguishedName
IdentityReference = $admin
IdentityReferenceSID = $SID
Right = 'CA Administrator'
Issue = @"
$admin has been granted CA Administrator rights on this Certification Authority (CA).

$admin has full control over this CA.

More info:
- https://posts.specterops.io/certified-pre-owned-d95910965cd2

"@
Fix = "Revoke CA Administrator rights from ${admin}."
Revert = "Restore CA Administrator rights to ${admin}."
Technique = 'ESC7'
}

if ($SkipRisk -eq $false) {
Set-RiskRating -ADCSObjects $ADCSObjects -Issue $Issue -SafeUsers $SafeUsers -UnsafeUsers $UnsafeUsers
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC7Remediation -Issue $Issue
}

$Issue
}
}

Write-Output $object.CertificateManager -PipelineVariable admin | ForEach-Object {
$SID = Convert-IdentityReferenceToSid -Object $admin
if ($SID -notmatch $SafeUsers) {
$Issue = [pscustomobject]@{
Forest = $object.CanonicalName.split('/')[0]
Name = $object.Name
DistinguishedName = $object.DistinguishedName
IdentityReference = $admin
IdentityReferenceSID = $SID
Right = 'Certificate Manager'
Issue = @"
$admin has been granted Certificate Manager rights on this Certification Authority (CA).

$admin can approve pending certificate requests on this CA.

More info:
- https://posts.specterops.io/certified-pre-owned-d95910965cd2

"@
Fix = "Revoke Certificate Manager rights from ${admin}."
Revert = "Restore Certificate Manager rights to ${admin}."
Technique = 'ESC7'
}

if ($SkipRisk -eq $false) {
Set-RiskRating -ADCSObjects $ADCSObjects -Issue $Issue -SafeUsers $SafeUsers -UnsafeUsers $UnsafeUsers
}

if ( $Mode -in @(1, 3, 4) ) {
Update-ESC7Remediation -Issue $Issue
}

$Issue
}
}
}
}
}
Loading