Skip to content

Commit 79a9b84

Browse files
Prepare domain object attributes for ADCS ESC6 (#94)
* Prepare domain object attributes for ADCS ESC6 * Correct property parsing, add produce false properties for uac * Correct email tests for ReadUser and ReadComputer Properties
1 parent 4988061 commit 79a9b84

3 files changed

Lines changed: 51 additions & 50 deletions

File tree

src/CommonLib/Processors/LDAPPropertyProcessor.cs

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -148,42 +148,26 @@ public async Task<UserProperties> ReadUserProperties(ISearchResultEntry entry)
148148
{
149149
var userProps = new UserProperties();
150150
var props = GetCommonProps(entry);
151-
151+
152+
var uacFlags = (UacFlags)0;
152153
var uac = entry.GetProperty(LDAPProperties.UserAccountControl);
153-
bool enabled, trustedToAuth, sensitive, dontReqPreAuth, passwdNotReq, unconstrained, pwdNeverExpires;
154154
if (int.TryParse(uac, out var flag))
155155
{
156-
var flags = (UacFlags)flag;
157-
enabled = (flags & UacFlags.AccountDisable) == 0;
158-
trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
159-
sensitive = (flags & UacFlags.NotDelegated) != 0;
160-
dontReqPreAuth = (flags & UacFlags.DontReqPreauth) != 0;
161-
passwdNotReq = (flags & UacFlags.PasswordNotRequired) != 0;
162-
unconstrained = (flags & UacFlags.TrustedForDelegation) != 0;
163-
pwdNeverExpires = (flags & UacFlags.DontExpirePassword) != 0;
164-
}
165-
else
166-
{
167-
trustedToAuth = false;
168-
enabled = true;
169-
sensitive = false;
170-
dontReqPreAuth = false;
171-
passwdNotReq = false;
172-
unconstrained = false;
173-
pwdNeverExpires = false;
156+
uacFlags = (UacFlags)flag;
174157
}
158+
159+
props.Add("sensitive", uacFlags.HasFlag(UacFlags.NotDelegated));
160+
props.Add("dontreqpreauth", uacFlags.HasFlag(UacFlags.DontReqPreauth));
161+
props.Add("passwordnotreqd", uacFlags.HasFlag(UacFlags.PasswordNotRequired));
162+
props.Add("unconstraineddelegation", uacFlags.HasFlag(UacFlags.TrustedForDelegation));
163+
props.Add("pwdneverexpires", uacFlags.HasFlag(UacFlags.DontExpirePassword));
164+
props.Add("enabled", !uacFlags.HasFlag(UacFlags.AccountDisable));
165+
props.Add("trustedtoauth", uacFlags.HasFlag(UacFlags.TrustedToAuthForDelegation));
175166

176-
props.Add("sensitive", sensitive);
177-
props.Add("dontreqpreauth", dontReqPreAuth);
178-
props.Add("passwordnotreqd", passwdNotReq);
179-
props.Add("unconstraineddelegation", unconstrained);
180-
props.Add("pwdneverexpires", pwdNeverExpires);
181-
props.Add("enabled", enabled);
182-
props.Add("trustedtoauth", trustedToAuth);
183167
var domain = Helpers.DistinguishedNameToDomain(entry.DistinguishedName);
184168

185169
var comps = new List<TypedPrincipal>();
186-
if (trustedToAuth)
170+
if (uacFlags.HasFlag(UacFlags.TrustedToAuthForDelegation))
187171
{
188172
var delegates = entry.GetArrayProperty(LDAPProperties.AllowedToDelegateTo);
189173
props.Add("allowedtodelegate", delegates);
@@ -276,27 +260,23 @@ public async Task<ComputerProperties> ReadComputerProperties(ISearchResultEntry
276260
{
277261
var compProps = new ComputerProperties();
278262
var props = GetCommonProps(entry);
279-
263+
264+
var flags = (UacFlags)0;
280265
var uac = entry.GetProperty(LDAPProperties.UserAccountControl);
281-
bool enabled, unconstrained, trustedToAuth;
282266
if (int.TryParse(uac, out var flag))
283267
{
284-
var flags = (UacFlags)flag;
285-
enabled = (flags & UacFlags.AccountDisable) == 0;
286-
unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation;
287-
trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
288-
}
289-
else
290-
{
291-
unconstrained = false;
292-
enabled = true;
293-
trustedToAuth = false;
268+
flags = (UacFlags)flag;
294269
}
270+
271+
props.Add("enabled", !flags.HasFlag(UacFlags.AccountDisable));
272+
props.Add("unconstraineddelegation", flags.HasFlag(UacFlags.TrustedForDelegation));
273+
props.Add("trustedtoauth", flags.HasFlag(UacFlags.TrustedToAuthForDelegation));
274+
props.Add("isdc", flags.HasFlag(UacFlags.ServerTrustAccount));
295275

296276
var domain = Helpers.DistinguishedNameToDomain(entry.DistinguishedName);
297277

298278
var comps = new List<TypedPrincipal>();
299-
if (trustedToAuth)
279+
if (flags.HasFlag(UacFlags.TrustedToAuthForDelegation))
300280
{
301281
var delegates = entry.GetArrayProperty(LDAPProperties.AllowedToDelegateTo);
302282
props.Add("allowedtodelegate", delegates);
@@ -332,15 +312,13 @@ public async Task<ComputerProperties> ReadComputerProperties(ISearchResultEntry
332312

333313
compProps.AllowedToAct = allowedToActPrincipals.ToArray();
334314

335-
props.Add("enabled", enabled);
336-
props.Add("unconstraineddelegation", unconstrained);
337-
props.Add("trustedtoauth", trustedToAuth);
338315
props.Add("lastlogon", Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.LastLogon)));
339316
props.Add("lastlogontimestamp",
340317
Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.LastLogonTimestamp)));
341318
props.Add("pwdlastset",
342319
Helpers.ConvertFileTimeToUnixEpoch(entry.GetProperty(LDAPProperties.PasswordLastSet)));
343320
props.Add("serviceprincipalnames", entry.GetArrayProperty(LDAPProperties.ServicePrincipalNames));
321+
props.Add("email", entry.GetProperty(LDAPProperties.Email));
344322
var os = entry.GetProperty(LDAPProperties.OperatingSystem);
345323
var sp = entry.GetProperty(LDAPProperties.ServicePack);
346324

@@ -516,6 +494,16 @@ public static Dictionary<string, object> ReadCertTemplateProperties(ISearchResul
516494
nameFlags.HasFlag(PKICertificateNameFlag.ENROLLEE_SUPPLIES_SUBJECT));
517495
props.Add("subjectaltrequireupn",
518496
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_ALT_REQUIRE_UPN));
497+
props.Add("subjectaltrequiredns",
498+
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_ALT_REQUIRE_DNS));
499+
props.Add("subjectaltrequiredomaindns",
500+
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_ALT_REQUIRE_DOMAIN_DNS));
501+
props.Add("subjectaltrequireemail",
502+
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_ALT_REQUIRE_EMAIL));
503+
props.Add("subjectaltrequirespn",
504+
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_ALT_REQUIRE_SPN));
505+
props.Add("subjectrequireemail",
506+
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_REQUIRE_EMAIL));
519507
}
520508

521509
string[] ekus = entry.GetArrayProperty(LDAPProperties.ExtendedKeyUsage);
@@ -761,4 +749,4 @@ public class ComputerProperties
761749
public TypedPrincipal[] SidHistory { get; set; } = Array.Empty<TypedPrincipal>();
762750
public TypedPrincipal[] DumpSMSAPassword { get; set; } = Array.Empty<TypedPrincipal>();
763751
}
764-
}
752+
}

src/CommonLib/SearchResultEntryWrapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public ResolvedSearchResult ResolveBloodHoundInfo()
6363
if (int.TryParse(uac, out var flag))
6464
{
6565
var flags = (UacFlags) flag;
66-
if ((flags & UacFlags.ServerTrustAccount) != 0)
66+
if (flags.HasFlag(UacFlags.ServerTrustAccount))
6767
{
6868
_log.LogTrace("Marked {SID} as a domain controller", objectId);
6969
res.IsDomainController = true;

test/unit/LDAPPropertyTests.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_HappyPath()
264264
{"lastlogon", "132673011142753043"},
265265
{"lastlogontimestamp", "132670318095676525"},
266266
{"homedirectory", @"\\win10\testdir"},
267+
{"mail", "test@testdomain.com"},
267268
{
268269
"serviceprincipalname", new[]
269270
{
@@ -298,6 +299,8 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_HappyPath()
298299
Assert.Equal(1568693134, (long)props["pwdlastset"]);
299300
Assert.Contains("homedirectory", keys);
300301
Assert.Equal(@"\\win10\testdir", props["homedirectory"] as string);
302+
Assert.Contains("email", keys);
303+
Assert.Equal("test@testdomain.com", props["email"] as string);
301304

302305
//UAC stuff
303306
Assert.Contains("sensitive", keys);
@@ -397,6 +400,7 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_HappyPath()
397400
{"lastlogontimestamp", "132670318095676525"},
398401
{"operatingsystem", "Windows 10 Enterprise"},
399402
{"operatingsystemservicepack", "1607"},
403+
{"mail", "test@testdomain.com"},
400404
{"admincount", "c"},
401405
{
402406
"sidhistory", new[]
@@ -434,11 +438,15 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_HappyPath()
434438
//UAC
435439
Assert.Contains("enabled", keys);
436440
Assert.Contains("unconstraineddelegation", keys);
441+
Assert.Contains("trustedtoauth", keys);
442+
Assert.Contains("isdc", keys);
437443
Assert.Contains("lastlogon", keys);
438444
Assert.Contains("lastlogontimestamp", keys);
439445
Assert.Contains("pwdlastset", keys);
440446
Assert.True((bool)props["enabled"]);
441447
Assert.False((bool)props["unconstraineddelegation"]);
448+
Assert.True((bool)props["trustedtoauth"]);
449+
Assert.False((bool)props["isdc"]);
442450

443451
Assert.Contains("lastlogon", keys);
444452
Assert.Equal(1622827514, (long)props["lastlogon"]);
@@ -462,6 +470,8 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_HappyPath()
462470
Assert.Equal("Windows 10 Enterprise 1607", props["operatingsystem"] as string);
463471
Assert.Contains("description", keys);
464472
Assert.Equal("Test", props["description"] as string);
473+
Assert.Contains("email", keys);
474+
Assert.Equal("test@testdomain.com", props["email"] as string);
465475

466476
//SidHistory
467477
Assert.Contains("sidhistory", keys);
@@ -700,9 +710,7 @@ public void LDAPPropertyProcessor_ReadCertTemplateProperties()
700710
{"oid", "1.3.6.1.4.1.311.21.8.4571196.1884641.3293620.10686285.12068043.134.1.30"},
701711
{"enrollmentflag", 32},
702712
{"requiresmanagerapproval", false},
703-
{"certificatenameflag", 134217728},
704-
{"enrolleesuppliessubject", false},
705-
{"subjectaltrequireupn", false},
713+
{"certificatenameflag", 0x8000000},
706714
{"ekus", new[]
707715
{"1.3.6.1.5.5.7.3.2"}
708716
},
@@ -739,6 +747,11 @@ public void LDAPPropertyProcessor_ReadCertTemplateProperties()
739747
Assert.Contains("certificatenameflag", keys);
740748
Assert.Contains("enrolleesuppliessubject", keys);
741749
Assert.Contains("subjectaltrequireupn", keys);
750+
Assert.Contains("subjectaltrequiredns", keys);
751+
Assert.Contains("subjectaltrequiredomaindns", keys);
752+
Assert.Contains("subjectaltrequireemail", keys);
753+
Assert.Contains("subjectaltrequirespn", keys);
754+
Assert.Contains("subjectrequireemail", keys);
742755
Assert.Contains("ekus", keys);
743756
Assert.Contains("certificateapplicationpolicy", keys);
744757
Assert.Contains("authorizedsignatures", keys);
@@ -833,4 +846,4 @@ public void LDAPPropertyProcessor_ParseAllProperties_CollectionCountOne_NotBadPa
833846
}
834847

835848
}
836-
}
849+
}

0 commit comments

Comments
 (0)