44using System . Security . AccessControl ;
55using System . Security . Principal ;
66using winPEAS . Helpers ;
7+ using winPEAS . Helpers . Registry ;
8+ using winPEAS . Info . FilesInfo . Certificates ;
79
810namespace winPEAS . Checks
911{
@@ -17,7 +19,7 @@ public void PrintInfo(bool isDebug)
1719 new List < Action >
1820 {
1921 PrintGmsaReadableByCurrentPrincipal ,
20- PrintAdcsEsc4LikeTemplates
22+ PrintAdcsMisconfigurations
2123 } . ForEach ( action => CheckRunner . Run ( action , isDebug ) ) ;
2224 }
2325
@@ -152,22 +154,91 @@ private void PrintGmsaReadableByCurrentPrincipal()
152154 }
153155 }
154156
155- // Detect AD CS certificate templates where current principal has dangerous control rights (ESC4-style)
156- private void PrintAdcsEsc4LikeTemplates ( )
157+ // Detect AD CS misconfigurations
158+ private void PrintAdcsMisconfigurations ( )
157159 {
158160 try
159161 {
160- Beaprint . MainPrint ( "AD CS templates with dangerous ACEs (ESC4)" ) ;
161- Beaprint . LinkPrint (
162- "https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/ad-certificates.html#esc4" ,
163- "If you can modify a template (WriteDacl/WriteOwner/GenericAll), you can abuse ESC4" ) ;
164-
162+ Beaprint . MainPrint ( "AD CS misconfigurations for ESC" ) ;
163+ Beaprint . LinkPrint ( "https://book.hacktricks.wiki/en/windows-hardening/active-directory-methodology/ad-certificates.html" ) ;
164+
165165 if ( ! Checks . IsPartOfDomain )
166166 {
167167 Beaprint . GrayPrint ( " [-] Host is not domain-joined. Skipping." ) ;
168168 return ;
169169 }
170170
171+ Beaprint . InfoPrint ( "Check for ADCS misconfigurations in the local DC registry" ) ;
172+ bool IsDomainController = RegistryHelper . GetReg ( "HKLM" , @"SYSTEM\CurrentControlSet\Services\NTDS" ) ? . ValueCount > 0 ;
173+ if ( IsDomainController )
174+ {
175+ // For StrongBinding and CertificateMapping, More details in KB014754 - Registry key information:
176+ // https://support.microsoft.com/en-us/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16
177+ uint ? strongBinding = RegistryHelper . GetDwordValue ( "HKLM" , @"SYSTEM\CurrentControlSet\Services\Kdc" , "StrongCertificateBindingEnforcement" ) ;
178+ switch ( strongBinding )
179+ {
180+ case 0 :
181+ Beaprint . BadPrint ( " StrongCertificateBindingEnforcement: 0 — Weak mapping allowed, vulnerable to ESC9." ) ;
182+ break ;
183+ case 2 :
184+ Beaprint . GoodPrint ( " StrongCertificateBindingEnforcement: 2 — Prevents weak UPN/DNS mappings even if SID extension missing, not vulnerable to ESC9." ) ;
185+ break ;
186+ // 1 is default behavior now I think?
187+ case 1 :
188+ default :
189+ Beaprint . NoColorPrint ( $ " StrongCertificateBindingEnforcement: { strongBinding } — Allow weak mapping if SID extension missing, may be vulnerable to ESC9.") ;
190+ break ;
191+
192+ }
193+
194+ uint ? certMapping = RegistryHelper . GetDwordValue ( "HKLM" , @"SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL" , "CertificateMappingMethods" ) ;
195+ if ( certMapping . HasValue && ( certMapping & 0x4 ) != 0 )
196+ Beaprint . BadPrint ( $ " CertificateMappingMethods: { certMapping } — Allow UPN-based mapping, vulnerable to ESC10.") ;
197+ else if ( certMapping . HasValue && ( ( certMapping & 0x1 ) != 0 || ( certMapping & 0x2 ) != 0 ) )
198+ Beaprint . NoColorPrint ( $ " CertificateMappingMethods: { certMapping } — Allow weak Subject/Issuer certificate mapping.") ;
199+ // 0x18 (strong mapping) is default behavior if not the flags above I think?
200+ else
201+ Beaprint . GoodPrint ( $ " CertificateMappingMethods: { certMapping } — Strong Certificate mapping enabled.") ;
202+
203+ // We take the Active CA, can they be several?
204+ string caName = RegistryHelper . GetRegValue ( "HKLM" , $@ "SYSTEM\CurrentControlSet\Services\CertSvc\Configuration", "Active" ) ;
205+ if ( ! string . IsNullOrWhiteSpace ( caName ) )
206+ {
207+ // Obscure Source for InterfaceFlag Enum:
208+ // https://www.sysadmins.lv/apidocs/pki/html/T_PKI_CertificateServices_Flags_InterfaceFlagEnum.htm
209+ uint ? interfaceFlags = RegistryHelper . GetDwordValue ( "HKLM" , $@ "SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{ caName } ", "InterfaceFlags" ) ;
210+ if ( ! interfaceFlags . HasValue || ( interfaceFlags & 512 ) == 0 )
211+ Beaprint . BadPrint ( " IF_ENFORCEENCRYPTICERTREQUEST not set in InterfaceFlags — vulnerable to ESC11." ) ;
212+ else
213+ Beaprint . GoodPrint ( " IF_ENFORCEENCRYPTICERTREQUEST set in InterfaceFlags — not vulnerable to ESC11." ) ;
214+
215+ string policyModule = RegistryHelper . GetRegValue ( "HKLM" , $@ "SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{ caName } \PolicyModules", "Active" ) ;
216+ if ( ! string . IsNullOrWhiteSpace ( policyModule ) )
217+ {
218+ string disableExtensionList = RegistryHelper . GetRegValue ( "HKLM" , $@ "SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\{ caName } \PolicyModules\{ policyModule } ", "DisableExtensionList" ) ;
219+ // zOID_NTDS_CA_SECURITY_EXT (OID 1.3.6.1.4.1.311.25.2)
220+ if ( disableExtensionList ? . Contains ( "1.3.6.1.4.1.311.25.2" ) == true )
221+ Beaprint . BadPrint ( " szOID_NTDS_CA_SECURITY_EXT disabled for the entire CA — vulnerable to ESC16." ) ;
222+ else
223+ Beaprint . GoodPrint ( " szOID_NTDS_CA_SECURITY_EXT not disabled for the CA — not vulnerable to ESC16." ) ;
224+ }
225+ else
226+ {
227+ Beaprint . GrayPrint ( " [-] Policy Module not found. Skipping." ) ;
228+ }
229+ }
230+ else
231+ {
232+ Beaprint . GrayPrint ( " [-] Certificate Authority not found. Skipping." ) ;
233+ }
234+ }
235+ else
236+ {
237+ Beaprint . GrayPrint ( " [-] Host is not a domain controller. Skipping ADCS Registry check" ) ;
238+ }
239+
240+ // Detect AD CS certificate templates where current principal has dangerous control rights(ESC4 - style)
241+ Beaprint . InfoPrint ( "\n If you can modify a template (WriteDacl/WriteOwner/GenericAll), you can abuse ESC4" ) ;
171242 var configNC = GetRootDseProp ( "configurationNamingContext" ) ;
172243 if ( string . IsNullOrEmpty ( configNC ) )
173244 {
0 commit comments