Skip to content

Commit be3fe91

Browse files
authored
Merge pull request #507 from CravateRouge/master
Add ADCS ESC DC registry checks
2 parents c83eef9 + b8b4a0f commit be3fe91

File tree

1 file changed

+79
-8
lines changed

1 file changed

+79
-8
lines changed

winPEAS/winPEASexe/winPEAS/Checks/ActiveDirectoryInfo.cs

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System.Security.AccessControl;
55
using System.Security.Principal;
66
using winPEAS.Helpers;
7+
using winPEAS.Helpers.Registry;
8+
using winPEAS.Info.FilesInfo.Certificates;
79

810
namespace 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("\nIf 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

Comments
 (0)