From 6e50c67d6177fa5927ea176a64a7b611820f1611 Mon Sep 17 00:00:00 2001 From: Lars Karlslund Date: Fri, 6 May 2022 18:59:43 +0200 Subject: [PATCH] Resolve GPO group assignments that contain %Computername% etc. in them to the real groups --- .../activedirectory/analyze/analyze-ad.go | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/modules/integrations/activedirectory/analyze/analyze-ad.go b/modules/integrations/activedirectory/analyze/analyze-ad.go index 08c29ac..4b4dc00 100644 --- a/modules/integrations/activedirectory/analyze/analyze-ad.go +++ b/modules/integrations/activedirectory/analyze/analyze-ad.go @@ -1500,4 +1500,58 @@ func init() { engine.AfterMerge, ) + Loader.AddProcessor(func(ao *engine.Objects) { + for _, gpo := range ao.Filter(func(o *engine.Object) bool { + return o.Type() == engine.ObjectTypeGroupPolicyContainer + }).Slice() { + for group, methods := range gpo.PwnableBy { + + groupname := group.OneAttrString(engine.SAMAccountName) + if strings.Contains(groupname, "%") { + // Lowercase for ease + groupname := strings.ToLower(groupname) + + // It has some sort of % variable in it, let's go + for affected, amethods := range gpo.CanPwn { + if amethods.IsSet(activedirectory.PwnAffectedByGPO) && affected.Type() == engine.ObjectTypeComputer { + netbiosdomain, computername, found := strings.Cut(affected.OneAttrString(engine.DownLevelLogonName), "\\") + if !found { + log.Error().Msgf("Could not parse downlevel logon name %v", affected.OneAttrString(engine.DownLevelLogonName)) + continue + } + computername = strings.TrimRight(computername, "$") + + realgroup := groupname + realgroup = strings.Replace(realgroup, "%computername%", computername, -1) + realgroup = strings.Replace(realgroup, "%domainname%", netbiosdomain, -1) + realgroup = strings.Replace(realgroup, "%domain%", netbiosdomain, -1) + + var targetgroups []*engine.Object + + if !strings.Contains(realgroup, "\\") { + realgroup = netbiosdomain + "\\" + realgroup + } + targetgroups, _ = ao.FindMulti( + engine.DownLevelLogonName, engine.AttributeValueString(realgroup), + ) + + if len(targetgroups) == 0 { + log.Warn().Msgf("Could not find group %v", realgroup) + } else if len(targetgroups) == 1 { + for _, method := range methods.Methods() { + targetgroups[0].PwnsEx(affected, method, true) + } + } else { + log.Warn().Msgf("Found multiple groups for %v: %v", realgroup, targetgroups) + } + } + } + } + + } + } + }, "Resolve expanding group names to real names from GPOs", + engine.AfterMerge, + ) + }