diff --git a/src/CommonLib/OutputTypes/ResultingGPOChanges.cs b/src/CommonLib/OutputTypes/ResultingGPOChanges.cs index 6909d1f2..8314bac9 100644 --- a/src/CommonLib/OutputTypes/ResultingGPOChanges.cs +++ b/src/CommonLib/OutputTypes/ResultingGPOChanges.cs @@ -22,5 +22,6 @@ public class GPOChanges public Dictionary SMBSigning = new(); public Dictionary LDAPSigning = new(); public Dictionary LMAuthenticationLevel = new(); + public Dictionary MSCache = new(); } } \ No newline at end of file diff --git a/src/CommonLib/Processors/GPOLocalGroupProcessor.cs b/src/CommonLib/Processors/GPOLocalGroupProcessor.cs index d5472316..976d958d 100644 --- a/src/CommonLib/Processors/GPOLocalGroupProcessor.cs +++ b/src/CommonLib/Processors/GPOLocalGroupProcessor.cs @@ -86,6 +86,12 @@ public class GPOLocalGroupProcessor private static readonly Regex LMLevelRegex = new(@"\\LmCompatibilityLevel *= *\d+ *, *(\d)", RegexOptions.Compiled); + private static readonly Regex CachedLogonsCountRegex = + new(@"\\CachedLogonsCount *= *\d+ *, *\x22(\d+)\x22", RegexOptions.Compiled); + + private static readonly Regex LDAPEnforceChannelBindingRegex = + new(@"\\LdapEnforceChannelBinding *= *\d+ *, *(\d)", RegexOptions.Compiled); + private static readonly ConcurrentDictionary> GpoActionCache = new(); private static readonly Dictionary ValidGroupNames = @@ -228,10 +234,22 @@ public async Task ReadGPOLocalGroups(string gpLink, string } // Add LM properties - _ = enforced.Contains(linkDn) ? (ret.Enforced.LMAuthenticationLevel = item.GPOLMProps) : (ret.Unenforced.LMAuthenticationLevel = item.GPOLMProps); + foreach (var i in item.GPOLMProps) + { + _ = enforced.Contains(linkDn) ? (ret.Enforced.LMAuthenticationLevel = item.GPOLMProps) : (ret.Unenforced.LMAuthenticationLevel = item.GPOLMProps); + } // Add LDAP properties - _ = enforced.Contains(linkDn) ? (ret.Enforced.LDAPSigning = item.GPOLDAPProps) : (ret.Unenforced.LDAPSigning = item.GPOLDAPProps); + foreach (var i in item.GPOLDAPProps) + { + _ = enforced.Contains(linkDn) ? (ret.Enforced.LDAPSigning[i.Key] = i.Value) : (ret.Unenforced.LDAPSigning[i.Key] = i.Value); + } + + // Add MSCache properties + foreach (var i in item.GPOMSCache) + { + _ = enforced.Contains(linkDn) ? (ret.Enforced.MSCache = item.GPOMSCache) : (ret.Unenforced.MSCache = item.GPOMSCache); + } } } @@ -241,7 +259,6 @@ public async Task ReadGPOLocalGroups(string gpLink, string //If there are no actions, then we can skip some instructions if (actions.Count != 0) { - //First lets process restricted members var restrictedMemberSets = actions.Where(x => x.Target == GroupActionTarget.RestrictedMember) .GroupBy(x => x.TargetRid); @@ -468,6 +485,7 @@ internal async IAsyncEnumerable ProcessGPOTemplateFile(string ba ret.GPOLDAPProps = new Dictionary(); ret.GPOSMBProps = new Dictionary(); ret.GPOLMProps = new Dictionary(); + ret.GPOMSCache = new Dictionary(); // check for registries var regMatch = RegistryRegex.Match(content); @@ -479,9 +497,11 @@ internal async IAsyncEnumerable ProcessGPOTemplateFile(string ba bool EnablesClientSMB = false; bool RequiresLDAPSigning = false; + bool LDAPEnforceChannelBinding = false; - int LmCompatibilityLevel = 3; // default value for W10 = 3 according to https://docs.microsoft.com/fr-fr/windows/security/threat-protection/security-policy-settings/network-security-lan-manager-authentication-level + int LmCompatibilityLevel = 3; + int CachedLogonsCount = 0; // if registry section is found if (regMatch.Success) @@ -499,9 +519,11 @@ internal async IAsyncEnumerable ProcessGPOTemplateFile(string ba var smbEnableClientMatchLine = SMBEnableClientRegex.Match(regLine); var ldapClientMatchLine = LDAPClientIntegrityRegex.Match(regLine); + var ldapChannelBindingLine = LDAPEnforceChannelBindingRegex.Match(regLine); var lmMatchLine = LMLevelRegex.Match(regLine); + var cachedLogonsLine = CachedLogonsCountRegex.Match(regLine); // if a match is found for this registry if (smbRequireServerMatchLine.Success) @@ -601,6 +623,35 @@ internal async IAsyncEnumerable ProcessGPOTemplateFile(string ba ret.GPOLDAPProps.Add("RequiresLDAPClientSigning", RequiresLDAPSigning); } + else if (ldapChannelBindingLine.Success) + { + var keyMatch = KeyRegex.Match(regLine); + var key = keyMatch.Value.Split(',')[1]; + + switch (key) + { + case "2": // Always enabled + LDAPEnforceChannelBinding = true; + break; + case "1": // Enabled, if supported + LDAPEnforceChannelBinding = false; + break; + case "0": // Disabled + LDAPEnforceChannelBinding = false; + break; + } + + ret.GPOLDAPProps.Add("LDAPEnforceChannelBinding", LDAPEnforceChannelBinding); + } + else if (cachedLogonsLine.Success) + { + var keyMatch = KeyRegex.Match(regLine); + var key = keyMatch.Value.Split(',')[1]; + CachedLogonsCount = Int32.Parse(key.Substring(1, key.Length - 2)); + + ret.GPOMSCache.Add("CachedLogonsCount", CachedLogonsCount); + + } } } @@ -960,6 +1011,7 @@ internal class GPOReturnTuple public Dictionary GPOLDAPProps = new(); public Dictionary GPOSMBProps = new(); public Dictionary GPOLMProps = new(); + public Dictionary GPOMSCache = new(); public GroupAction GPOGroupAction = new(); public bool ContainsGroupAction()