├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jake Hildreth 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # adcs-snippets 2 | Just a bunch of code snippets to identify and remediate common Active Directory Certificate Services issues. 3 | 4 | ## Common Misconfiguration #1: Insufficient Auditing 5 | ### Check current configuration 6 | ```powershell 7 | certutil -getreg CA\AuditFilter 8 | ```` 9 | 10 | If you receive a result like the following, auditing is not enabled: 11 | ```batch 12 | HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\horse-CA1-CA-1\AuditFilter: 13 | 14 | AuditFilter REG_DWORD = 0 15 | CertUtil: -getreg command completed successfully. 16 | ``` 17 | 18 | ### Enable all auditing 19 | ```powershell 20 | certutil –setreg CA\AuditFilter 127 21 | net stop certsvc 22 | net start certsvc 23 | ``` 24 | 25 | Notes: 26 | - These snippets must be run on each CA host individually. 27 | - Fully enabling auditing requires 2 additional GPO settings to be configured. 28 | 29 | ## Common Misconfiguration #2: Single-Tier Architecture 30 | Wonderful guide by Pete Long on building a two-tier PKI: https://www.petenetlive.com/KB/Article/0001309 31 | 32 | ## Common Misconfiguration #3: Unsafe Ownership 33 | ### Find Objects with Unsafe Owners 34 | ```powershell 35 | $ADRoot = (Get-ADRootDSE).rootDomainNamingContext 36 | 37 | $Safe_Owners = "Enterprise Admins|Domain Admins|Administrators" 38 | 39 | $ADCS_Objects = Get-ADObject -Filter * -SearchBase "CN=Public Key Services,CN=Services,CN=Configuration,$ADRoot" -SearchScope 2 -Properties * 40 | 41 | $ADCS_Objects | Where-Object { 42 | $_.nTSecurityDescriptor.Owner -notmatch $Safe_Owners 43 | } | Format-Table Name,DistinguishedName 44 | ``` 45 | 46 | ### Reset Owner to "Enterprise Admins" 47 | ```powershell 48 | $DNSRoot = (Get-ADDomain).DNSRoot 49 | $StandardOwner = New-Object System.Security.Principal.NTAccount($DNSRoot, "Enterprise Admins") 50 | 51 | $ADCS_Objects_BadOwner = $ADCS_Objects | Where-Object { 52 | $_.nTSecurityDescriptor.Owner -notmatch $Safe_Owners 53 | } 54 | 55 | $ADCS_Objects_BadOwner | ForEach-Object { 56 | $ObjectPath = "AD:$($_.DistinguishedName)" 57 | $ACL = Get-Acl -Path $ObjectPath 58 | $ACL.SetOwner($StandardOwner) 59 | Set-ACL -Path $ObjectPath -AclObject $ACL 60 | } 61 | ``` 62 | 63 | ## Dangerous Misconfiguration #1: Unsafe ACLs 64 | ### Find Objects with Dangerous ACLs 65 | ```powershell 66 | $Safe_Users = "Domain Admins|Enterprise Admins BUILTIN\\Administrators NT AUTHORITY\\SYSTEM|$env:userdomain\\Cert Publishers|$env:userdomain\\Administrator" 67 | 68 | $DangerousRights = "GenericAll|WriteDacl|WriteOwner" 69 | 70 | foreach ( $object in $ADCS_Objects ) { 71 | $BadACE = $object.nTSecurityDescriptor.Access | Where-Object { 72 | ( $.IdentityReference -notmatch $Safe_Users ) -and ( $_.ActiveDirectoryRights -match $DangerousRights ) 73 | } 74 | if ( $BadACE ) { 75 | Write-Host "Object: $object" -ForegroundColor Red 76 | $BadACE 77 | } 78 | } 79 | ``` 80 | *Note: This snippet is very simple will likely return some false positives. CAs, PKI Admin users/groups, and other safe entities may end up in the results. This list should be a starting point for future investigation.* 81 | 82 | ## Dangerous Misconfiguration #2: Templates with Bad Configs 83 | ### Find Templates with Bad Configs 84 | ```powershell 85 | $ClientAuthEKUs = "1\.3\.6\.1\.5\.5\.7\.3\.2| 86 | 1\.3\.6\.1\.5\.2\.3\.4| 87 | 1\.3\.6\.1\.4\.1\.311\.20\.2\.2| 88 | 2\.5\.29\.37\.0" 89 | 90 | $ADCS_Objects | Where-Object { 91 | ($_.ObjectClass -eq "pKICertificateTemplate") -and 92 | ($_.pkiExtendedKeyUsage -match $ClientAuthEKUs) -and 93 | ($_."msPKI-Certificate-Name-Flag" -band 1) -and 94 | !($_.'msPKI-Enrollment-Flag' -band 2) -and 95 | ( ($_."msPKI-RA-Signature" -eq 0) -or ($null -eq $_."msPKI-RA-Signature") ) 96 | } | Format-Table Name,DistinguishedName 97 | ``` 98 | 99 | ### Fix #1 for Templates with Bad Configs - Remove Ability to Set a SAN 100 | ```powershell 101 | $ADCS_Objects_BadConfig = $ADCS_Objects | Where-Object { 102 | ($_.ObjectClass -eq "pKICertificateTemplate") -and 103 | ($_.pkiExtendedKeyUsage -match $ClientAuthEKUs) -and 104 | ($_."msPKI-Certificate-Name-Flag" -band 1) -and 105 | !($_.'msPKI-Enrollment-Flag' -band 2) -and 106 | ( ($_."msPKI-RA-Signature" -eq 0) -or ($null -eq $_."msPKI-RA-Signature") ) 107 | } 108 | 109 | $ADCS_Objects_BadConfig | ForEach-Object { 110 | $_."msPKI-Certificate-Name-Flag" = 0 111 | } 112 | ``` 113 | 114 | ### Fix #2 for Templates with Bad Configs - Require Manager Approval (generally less impactful) 115 | ```powershell 116 | $ADCS_Objects_BadConfig = $ADCS_Objects | Where-Object { 117 | ($_.ObjectClass -eq "pKICertificateTemplate") -and 118 | ($_.pkiExtendedKeyUsage -match $ClientAuthEKUs) -and 119 | ($_."msPKI-Certificate-Name-Flag" -band 1) -and 120 | !($_.'msPKI-Enrollment-Flag' -band 2) -and 121 | ( ($_."msPKI-RA-Signature" -eq 0) -or ($null -eq $_."msPKI-RA-Signature") ) 122 | } 123 | 124 | $ADCS_Objects_BadConfig | ForEach-Object { 125 | $_."msPKI-Enrollment-Flag" = 2 126 | } 127 | ``` 128 | 129 | ## Dangerous Misconfiguration #3: Dangerous Flag on CA 130 | ### Check if the Flag is Set 131 | ```powershell 132 | certutil -getreg policy\EditFlags 133 | ``` 134 | 135 | ### Unset the Dangerous Flag 136 | ```powershell 137 | certutil -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2 138 | ``` 139 | --------------------------------------------------------------------------------