Skip to content

Commit d165866

Browse files
authored
Merge branch 'testing' into feature-get-published-templates
2 parents b4eab30 + c56a7c5 commit d165866

6 files changed

+191
-55
lines changed

Invoke-Locksmith.ps1

+109-35
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,9 @@ function Find-ESC3Condition2 {
421421
$ADCSObjects | Where-Object {
422422
($_.objectClass -eq 'pKICertificateTemplate') -and
423423
($_.pkiExtendedKeyUsage -match $ClientAuthEKU) -and
424-
($_.'msPKI-Certificate-Name-Flag' -band 1) -and
425424
!($_.'msPKI-Enrollment-Flag' -band 2) -and
426-
($_.'msPKI-RA-Application-Policies' -eq '1.3.6.1.4.1.311.20.2.1') -and
427-
( ($_.'msPKI-RA-Signature' -eq 1) )
425+
($_.'msPKI-RA-Application-Policies' -match '1.3.6.1.4.1.311.20.2.1') -and
426+
($_.'msPKI-RA-Signature' -eq 1)
428427
} | ForEach-Object {
429428
foreach ($entry in $_.nTSecurityDescriptor.Access) {
430429
$Principal = New-Object System.Security.Principal.NTAccount($entry.IdentityReference)
@@ -1038,7 +1037,7 @@ function Format-Result {
10381037
ESC1 = 'ESC1 - Vulnerable Certificate Template - Authentication'
10391038
ESC2 = 'ESC2 - Vulnerable Certificate Template - Subordinate CA'
10401039
ESC3 = 'ESC3 - Vulnerable Certificate Template - Enrollment Agent'
1041-
ESC4 = 'ESC4 - Vulnerable Access Control - Certifcate Template'
1040+
ESC4 = 'ESC4 - Vulnerable Access Control - Certificate Template'
10421041
ESC5 = 'ESC5 - Vulnerable Access Control - PKI Object'
10431042
ESC6 = 'ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2 Flag Enabled'
10441043
ESC8 = 'ESC8 - HTTP/S Enrollment Enabled'
@@ -1629,7 +1628,7 @@ function Invoke-Scans {
16291628
16301629
.EXAMPLE
16311630
# Perform all scans
1632-
Invoke-Scans
1631+
Invoke-Scans
16331632
16341633
.EXAMPLE
16351634
# Perform only the 'Auditing' and 'ESC1' scans
@@ -1641,6 +1640,8 @@ function Invoke-Scans {
16411640
#>
16421641

16431642
[CmdletBinding()]
1643+
[OutputType([hashtable])]
1644+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Invoke-Scans', Justification = 'Performing multiple scans.')]
16441645
param (
16451646
# Could split Scans and PromptMe into separate parameter sets.
16461647
[Parameter()]
@@ -1974,17 +1975,35 @@ function Set-AdditionalCAProperty {
19741975

19751976
begin {
19761977
$CAEnrollmentEndpoint = @()
1977-
$code = @"
1978-
using System.Net;
1979-
using System.Security.Cryptography.X509Certificates;
1980-
public class TrustAllCertsPolicy : ICertificatePolicy {
1981-
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
1982-
return true;
1983-
}
1984-
}
1978+
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy') ) {
1979+
if ($PSVersionTable.PSEdition -eq 'Desktop') {
1980+
$code = @"
1981+
using System.Net;
1982+
using System.Security.Cryptography.X509Certificates;
1983+
public class TrustAllCertsPolicy : ICertificatePolicy {
1984+
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
1985+
return true;
1986+
}
1987+
}
1988+
"@
1989+
Add-Type -TypeDefinition $code -Language CSharp
1990+
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
1991+
}
1992+
else {
1993+
Add-Type @"
1994+
using System.Net;
1995+
using System.Security.Cryptography.X509Certificates;
1996+
using System.Net.Security;
1997+
public class TrustAllCertsPolicy {
1998+
public static bool TrustAllCerts(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
1999+
return true;
2000+
}
2001+
}
19852002
"@
1986-
Add-Type -TypeDefinition $code -Language CSharp
1987-
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
2003+
# Set the ServerCertificateValidationCallback
2004+
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [TrustAllCertsPolicy]::TrustAllCerts
2005+
}
2006+
}
19882007
}
19892008

19902009
process {
@@ -2010,7 +2029,7 @@ public class TrustAllCertsPolicy : ICertificatePolicy {
20102029
try {
20112030
$FullURL = "https$URL"
20122031
$Request = [System.Net.WebRequest]::Create($FullURL)
2013-
2032+
20142033
$Request.GetResponse() | Out-Null
20152034
$CAEnrollmentEndpoint += @{
20162035
'URL' = $FullURL
@@ -2047,7 +2066,7 @@ public class TrustAllCertsPolicy : ICertificatePolicy {
20472066
$CAHostFQDN = (Get-ADObject -Filter { (Name -eq $CAHostName) -and (objectclass -eq 'computer') } -Properties DnsHostname -Server $ForestGC).DnsHostname
20482067
}
20492068
$ping = Test-Connection -ComputerName $CAHostFQDN -Quiet -Count 1
2050-
if ($ping) {
2069+
if ($ping) {
20512070
try {
20522071
if ($Credential) {
20532072
$CertutilAudit = Invoke-Command -ComputerName $CAHostname -Credential $Credential -ScriptBlock { param($CAFullName); certutil -config $CAFullName -getreg CA\AuditFilter } -ArgumentList $CAFullName
@@ -2110,6 +2129,7 @@ public class TrustAllCertsPolicy : ICertificatePolicy {
21102129
}
21112130

21122131
function Set-Severity {
2132+
[OutputType([string])]
21132133
[CmdletBinding()]
21142134
param(
21152135
[Parameter(Mandatory = $true)]
@@ -2145,6 +2165,44 @@ function Set-Severity {
21452165
}
21462166
}
21472167

2168+
function Show-LocksmithLogo {
2169+
Write-Host '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
2170+
Write-Host '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
2171+
Write-Host '%%%%%%%%%%%%%%%%%#+==============#%%%%%%%%%%%%%%%%%'
2172+
Write-Host '%%%%%%%%%%%%%%#=====================#%%%%%%%%%%%%%%'
2173+
Write-Host '%%%%%%%%%%%%#=========================#%%%%%%%%%%%%'
2174+
Write-Host '%%%%%%%%%%%=============================%%%%%%%%%%%'
2175+
Write-Host '%%%%%%%%%#==============+++==============#%%%%%%%%%'
2176+
Write-Host '%%%%%%%%#===========#%%%%%%%%%#===========#%%%%%%%%'
2177+
Write-Host '%%%%%%%%==========%%%%%%%%%%%%%%%==========%%%%%%%%'
2178+
Write-Host '%%%%%%%*=========%%%%%%%%%%%%%%%%%=========*%%%%%%%'
2179+
Write-Host '%%%%%%%+========*%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2180+
Write-Host '%%%%%%%+========#%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2181+
Write-Host '%%%%%%%+========#%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2182+
Write-Host '%%%%%%%+========#%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2183+
Write-Host '%%%%%%%+========#%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2184+
Write-Host '%%%%%%%+========#%%%%%%%%%%%%%%%%%#=========%%%%%%%'
2185+
Write-Host '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
2186+
Write-Host '#=================================================#'
2187+
Write-Host '#=================================================#'
2188+
Write-Host '#=================+%%%============================#'
2189+
Write-Host '#==================%%%%*==========================#'
2190+
Write-Host '#===================*%%%%+========================#'
2191+
Write-Host '#=====================#%%%%=======================#'
2192+
Write-Host '#======================+%%%%#=====================#'
2193+
Write-Host '#========================*%%%%*===================#'
2194+
Write-Host '#========================+%%%%%===================#'
2195+
Write-Host '#======================#%%%%%+====================#'
2196+
Write-Host '#===================+%%%%%%=======================#'
2197+
Write-Host '#=================#%%%%%+=========================#'
2198+
Write-Host '#==============+%%%%%#============================#'
2199+
Write-Host '#============*%%%%%+====+%%%%%%%%%%===============#'
2200+
Write-Host '#=============%%*========+********+===============#'
2201+
Write-Host '#=================================================#'
2202+
Write-Host '#=================================================#'
2203+
Write-Host '#=================================================#'
2204+
}
2205+
21482206
function Test-IsADAdmin {
21492207
<#
21502208
.SYNOPSIS
@@ -2237,9 +2295,11 @@ function Test-IsMemberOfProtectedUsers {
22372295
Active Directory user object, user SID, SamAccountName, etc
22382296
22392297
.OUTPUTS
2240-
True, False
2298+
Boolean
22412299
#>
22422300

2301+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Test-IsMemberOfProtectedUsers', Justification = 'The name of the group we are checking is plural.')]
2302+
[OutputType([Boolean])]
22432303
[CmdletBinding()]
22442304
param (
22452305
# User parameter accepts any input that is valid for Get-ADUser
@@ -2318,12 +2378,9 @@ function Test-IsRecentVersion {
23182378
Published at: 01/28/2024 12:47:18
23192379
Install Module: Install-Module -Name Locksmith
23202380
Standalone Script: https://github.com/trimarcjake/locksmith/releases/download/v2.6/Invoke-Locksmith.zip
2321-
2322-
.NOTES
2323-
Author: Sam Erde
2324-
Date: 02/10/2024
23252381
#>
23262382
[CmdletBinding()]
2383+
[OutputType([boolean])]
23272384
param (
23282385
# Check a specific version number from the script
23292386
[Parameter(Mandatory)]
@@ -2568,7 +2625,7 @@ function Invoke-Locksmith {
25682625
Finds the most common malconfigurations of Active Directory Certificate Services (AD CS).
25692626
25702627
.DESCRIPTION
2571-
Locksmith uses the Active Directory (AD) Powershell (PS) module to identify 6 misconfigurations
2628+
Locksmith uses the Active Directory (AD) Powershell (PS) module to identify 7 misconfigurations
25722629
commonly found in Enterprise mode AD CS installations.
25732630
25742631
.COMPONENT
@@ -2630,17 +2687,30 @@ function Invoke-Locksmith {
26302687

26312688
[CmdletBinding()]
26322689
param (
2633-
[string]$Forest,
2634-
[string]$InputPath,
2690+
#[string]$Forest, # Not used yet
2691+
#[string]$InputPath, # Not used yet
2692+
2693+
# The mode to run Locksmith in. Defaults to 0.
2694+
[Parameter()]
2695+
[ValidateSet(0, 1, 2, 3, 4)]
26352696
[int]$Mode = 0,
2697+
2698+
# The scans to run. Defaults to 'All'.
26362699
[Parameter()]
26372700
[ValidateSet('Auditing', 'ESC1', 'ESC2', 'ESC3', 'ESC4', 'ESC5', 'ESC6', 'ESC8', 'All', 'PromptMe')]
26382701
[array]$Scans = 'All',
2639-
[string]$OutputPath = (Get-Location).Path,
2702+
2703+
# The directory to save the output in (defaults to the current working directory).
2704+
[Parameter()]
2705+
[ValidateScript({ Test-Path -Path $_ -PathType Container })]
2706+
[string]$OutputPath = $PWD,
2707+
2708+
# The credential to use for working with ADCS.
2709+
[Parameter()]
26402710
[System.Management.Automation.PSCredential]$Credential
26412711
)
26422712

2643-
$Version = '2024.8'
2713+
$Version = '2024.10'
26442714
$LogoPart1 = @"
26452715
_ _____ _______ _ _ _______ _______ _____ _______ _ _
26462716
| | | | |____/ |______ | | | | | |_____|
@@ -2670,10 +2740,13 @@ function Invoke-Locksmith {
26702740
# Exit if running in restricted admin mode without explicit credentials
26712741
if (!$Credential -and (Get-RestrictedAdminModeSetting)) {
26722742
Write-Warning "Restricted Admin Mode appears to be in place, re-run with the '-Credential domain\user' option"
2673-
break;
2743+
break
26742744
}
26752745

26762746
### Initial variables
2747+
# For output filenames
2748+
[string]$FilePrefix = "Locksmith $(Get-Date -Format 'yyyy-MM-dd hh-mm-ss')"
2749+
26772750
# Extended Key Usages for client authentication. A requirement for ESC1
26782751
$ClientAuthEKUs = '1\.3\.6\.1\.5\.5\.7\.3\.2|1\.3\.6\.1\.5\.2\.3\.4|1\.3\.6\.1\.4\.1\.311\.20\.2\.2|2\.5\.29\.37\.0'
26792752

@@ -2723,18 +2796,20 @@ function Invoke-Locksmith {
27232796

27242797
### Generated variables
27252798
# $Dictionary = New-Dictionary
2799+
2800+
$Forest = Get-ADForest
27262801
$ForestGC = $(Get-ADDomainController -Discover -Service GlobalCatalog -ForceDiscover | Select-Object -ExpandProperty Hostname) + ":3268"
2727-
# $DNSRoot = [string]((Get-ADForest).RootDomain | Get-ADDomain).DNSRoot
2728-
$EnterpriseAdminsSID = ([string]((Get-ADForest).RootDomain | Get-ADDomain).DomainSID) + '-519'
2802+
# $DNSRoot = [string]($Forest.RootDomain | Get-ADDomain).DNSRoot
2803+
$EnterpriseAdminsSID = ([string]($Forest.RootDomain | Get-ADDomain).DomainSID) + '-519'
27292804
$PreferredOwner = [System.Security.Principal.SecurityIdentifier]::New($EnterpriseAdminsSID)
2730-
# $DomainSIDs = (Get-ADForest).Domains | ForEach-Object { (Get-ADDomain $_).DomainSID.Value }
2805+
# $DomainSIDs = $Forest.Domains | ForEach-Object { (Get-ADDomain $_).DomainSID.Value }
27312806

27322807
# Add SIDs of (probably) Safe Users to $SafeUsers
27332808
Get-ADGroupMember $EnterpriseAdminsSID | ForEach-Object {
27342809
$SafeUsers += '|' + $_.SID.Value
27352810
}
27362811

2737-
(Get-ADForest).Domains | ForEach-Object {
2812+
$Forest.Domains | ForEach-Object {
27382813
$DomainSID = (Get-ADDomain $_).DomainSID.Value
27392814
<#
27402815
-517 = Cert Publishers
@@ -2837,7 +2912,7 @@ function Invoke-Locksmith {
28372912
Format-Result $ESC8 '1'
28382913
}
28392914
2 {
2840-
$Output = 'ADCSIssues.CSV'
2915+
$Output = Join-Path -Path $OutputPath -ChildPath "$FilePrefix ADCSIssues.CSV"
28412916
Write-Host "Writing AD CS issues to $Output..."
28422917
try {
28432918
$AllIssues | Select-Object Forest, Technique, Name, Issue | Export-Csv -NoTypeInformation $Output
@@ -2848,7 +2923,7 @@ function Invoke-Locksmith {
28482923
}
28492924
}
28502925
3 {
2851-
$Output = 'ADCSRemediation.CSV'
2926+
$Output = Join-Path -Path $OutputPath -ChildPath "$FilePrefix ADCSRemediation.CSV"
28522927
Write-Host "Writing AD CS issues to $Output..."
28532928
try {
28542929
$AllIssues | Select-Object Forest, Technique, Name, DistinguishedName, Issue, Fix | Export-Csv -NoTypeInformation $Output
@@ -2867,5 +2942,4 @@ function Invoke-Locksmith {
28672942
}
28682943

28692944

2870-
# Export functions and aliases as required
28712945
Invoke-Locksmith -Mode $Mode -Scans $Scans

Locksmith.psd1

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Description = 'A small tool to find and fix common misconfigurations in Active Directory Certificate Services.'
88
FunctionsToExport = @('*')
99
GUID = 'b1325b42-8dc4-4f17-aa1f-dcb5984ca14a'
10-
ModuleVersion = '2024.8'
10+
ModuleVersion = '2024.10'
1111
PowerShellVersion = '5.1'
1212
PrivateData = @{
1313
PSData = @{

Private/Find-ESC3Condition2.ps1

+2-3
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@
3333
$ADCSObjects | Where-Object {
3434
($_.objectClass -eq 'pKICertificateTemplate') -and
3535
($_.pkiExtendedKeyUsage -match $ClientAuthEKU) -and
36-
($_.'msPKI-Certificate-Name-Flag' -band 1) -and
3736
!($_.'msPKI-Enrollment-Flag' -band 2) -and
38-
($_.'msPKI-RA-Application-Policies' -eq '1.3.6.1.4.1.311.20.2.1') -and
39-
( ($_.'msPKI-RA-Signature' -eq 1) )
37+
($_.'msPKI-RA-Application-Policies' -match '1.3.6.1.4.1.311.20.2.1') -and
38+
($_.'msPKI-RA-Signature' -eq 1)
4039
} | ForEach-Object {
4140
foreach ($entry in $_.nTSecurityDescriptor.Access) {
4241
$Principal = New-Object System.Security.Principal.NTAccount($entry.IdentityReference)

Private/Set-AdditionalCAProperty.ps1

+29-12
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,34 @@
3737

3838
begin {
3939
$CAEnrollmentEndpoint = @()
40-
$code= @"
41-
using System.Net;
42-
using System.Security.Cryptography.X509Certificates;
43-
public class TrustAllCertsPolicy : ICertificatePolicy {
44-
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
45-
return true;
46-
}
47-
}
40+
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy') ) {
41+
if ($PSVersionTable.PSEdition -eq 'Desktop') {
42+
$code= @"
43+
using System.Net;
44+
using System.Security.Cryptography.X509Certificates;
45+
public class TrustAllCertsPolicy : ICertificatePolicy {
46+
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
47+
return true;
48+
}
49+
}
4850
"@
49-
Add-Type -TypeDefinition $code -Language CSharp
50-
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
51+
Add-Type -TypeDefinition $code -Language CSharp
52+
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
53+
} else {
54+
Add-Type @"
55+
using System.Net;
56+
using System.Security.Cryptography.X509Certificates;
57+
using System.Net.Security;
58+
public class TrustAllCertsPolicy {
59+
public static bool TrustAllCerts(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
60+
return true;
61+
}
62+
}
63+
"@
64+
# Set the ServerCertificateValidationCallback
65+
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [TrustAllCertsPolicy]::TrustAllCerts
66+
}
67+
}
5168
}
5269

5370
process {
@@ -72,7 +89,7 @@ public class TrustAllCertsPolicy : ICertificatePolicy {
7289
try {
7390
$FullURL = "https$URL"
7491
$Request = [System.Net.WebRequest]::Create($FullURL)
75-
92+
7693
$Request.GetResponse() | Out-Null
7794
$CAEnrollmentEndpoint += @{
7895
'URL' = $FullURL
@@ -106,7 +123,7 @@ public class TrustAllCertsPolicy : ICertificatePolicy {
106123
$CAHostFQDN = (Get-ADObject -Filter { (Name -eq $CAHostName) -and (objectclass -eq 'computer') } -Properties DnsHostname -Server $ForestGC).DnsHostname
107124
}
108125
$ping = Test-Connection -ComputerName $CAHostFQDN -Quiet -Count 1
109-
if ($ping) {
126+
if ($ping) {
110127
try {
111128
if ($Credential) {
112129
$CertutilAudit = Invoke-Command -ComputerName $CAHostname -Credential $Credential -ScriptBlock { param($CAFullName); certutil -config $CAFullName -getreg CA\AuditFilter } -ArgumentList $CAFullName

0 commit comments

Comments
 (0)