Пример #1
0
        /// <summary>
        /// Processes an LDAP entry to resolve PrimaryGroup/MemberOf properties
        /// </summary>
        /// <param name="entry">LDAP entry</param>
        /// <param name="resolvedEntry">The resolved object with the name/type of the entry</param>
        /// <param name="domainSid">SID for the domain being enumerated. Used to resolve PrimaryGroupID</param>
        /// <returns></returns>
        public static IEnumerable <GroupMember> ProcessAdObject(SearchResultEntry entry, ResolvedEntry resolvedEntry, string domainSid)
        {
            var principalDisplayName = resolvedEntry.BloodHoundDisplay;
            var principalDomainName  = Utils.ConvertDnToDomain(entry.DistinguishedName);

            //If this object is a group, add it to our DN cache
            if (resolvedEntry.ObjectType.Equals("group"))
            {
                _cache.AddMapValue(entry.DistinguishedName, "group", principalDisplayName);
            }

            var members = entry.GetPropArray("member");

            if (members.Length == 0)
            {
                var tempMembers = new List <string>();
                var finished    = false;
                var bottom      = 0;

                while (!finished)
                {
                    var top   = bottom + 1499;
                    var range = $"member;range={bottom}-{top}";
                    bottom += 1500;
                    //Try ranged retrieval
                    foreach (var result in _utils.DoSearch("(objectclass=*)", SearchScope.Base, new[] { range },
                                                           principalDomainName,
                                                           entry.DistinguishedName))
                    {
                        if (result.Attributes.AttributeNames == null)
                        {
                            continue;
                        }
                        var en = result.Attributes.AttributeNames.GetEnumerator();

                        //If the enumerator fails, that means theres really no members at all
                        if (!en.MoveNext())
                        {
                            finished = true;
                            break;
                        }

                        if (en.Current == null)
                        {
                            continue;
                        }
                        var attrib = en.Current.ToString();
                        if (attrib.EndsWith("-*"))
                        {
                            finished = true;
                        }
                        tempMembers.AddRange(result.GetPropArray(attrib));
                    }
                }

                members = tempMembers.ToArray();
            }

            foreach (var dn in members)
            {
                //Check our cache first
                if (!_cache.GetMapValueUnknownType(dn, out var principal))
                {
                    if (dn.Contains("ForeignSecurityPrincipals") && dn.Contains("CN=S-1-5-21"))
                    {
                        var sid = dn.Split(',')[0].Substring(3);
                        principal = _utils.UnknownSidTypeToDisplay(sid, _utils.SidToDomainName(sid), Props);
                    }
                    else
                    {
                        var objEntry = _utils
                                       .DoSearch("(objectclass=*)", SearchScope.Base, Props, Utils.ConvertDnToDomain(dn), dn)
                                       .DefaultIfEmpty(null).FirstOrDefault();

                        if (objEntry == null)
                        {
                            principal = null;
                        }
                        else
                        {
                            var resolvedObj = objEntry.ResolveAdEntry();
                            if (resolvedObj == null)
                            {
                                principal = null;
                            }
                            else
                            {
                                _cache.AddMapValue(dn, resolvedObj.ObjectType, resolvedObj.BloodHoundDisplay);
                                principal = new MappedPrincipal
                                            (
                                    resolvedObj.BloodHoundDisplay,
                                    resolvedObj.ObjectType
                                            );
                            }
                        }
                    }
                }



                if (principal != null)
                {
                    yield return(new GroupMember
                    {
                        AccountName = principal.PrincipalName,
                        GroupName = principalDisplayName,
                        ObjectType = principal.ObjectType
                    });
                }
            }


            var pgi = entry.GetProp("primarygroupid");

            if (pgi == null)
            {
                yield break;
            }

            var pgsid            = $"{domainSid}-{pgi}";
            var primaryGroupName = _utils.SidToDisplay(pgsid, principalDomainName, Props, "group");

            if (primaryGroupName != null)
            {
                yield return new GroupMember
                       {
                           AccountName = resolvedEntry.BloodHoundDisplay,
                           GroupName   = primaryGroupName,
                           ObjectType  = resolvedEntry.ObjectType
                       }
            }
            ;
        }
Пример #2
0
        public static void GetGroupInfo(SearchResultEntry entry, ResolvedEntry resolved, string domainSid, ref Group u)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Group))
            {
                return;
            }

            var fMembers             = new List <GroupMember>();
            var principalDisplayName = resolved.BloodHoundDisplay;
            var principalDomainName  = Utils.ConvertDnToDomain(entry.DistinguishedName);

            if (resolved.ObjectType == "group")
            {
                _cache.AddMapValue(entry.DistinguishedName, "group", principalDisplayName);
            }

            var members = entry.GetPropArray("member");

            if (members.Length == 0)
            {
                var tempMembers = new List <string>();
                var finished    = false;
                var bottom      = 0;

                while (!finished)
                {
                    var top   = bottom + 1499;
                    var range = $"member;range={bottom}-{top}";
                    bottom += 1500;
                    //Try ranged retrieval
                    foreach (var result in _utils.DoSearch("(objectclass=*)", SearchScope.Base, new[] { range },
                                                           principalDomainName,
                                                           entry.DistinguishedName))
                    {
                        if (result.Attributes.AttributeNames == null)
                        {
                            continue;
                        }
                        var en = result.Attributes.AttributeNames.GetEnumerator();

                        //If the enumerator fails, that means theres really no members at all
                        if (!en.MoveNext())
                        {
                            finished = true;
                            break;
                        }

                        if (en.Current == null)
                        {
                            continue;
                        }
                        var attrib = en.Current.ToString();
                        if (attrib.EndsWith("-*"))
                        {
                            finished = true;
                        }

                        tempMembers.AddRange(result.GetPropArray(attrib));
                    }
                }

                members = tempMembers.ToArray();
            }

            foreach (var dn in members)
            {
                //Check our cache first
                if (!_cache.GetMapValueUnknownType(dn, out var principal))
                {
                    if (dn.Contains("ForeignSecurityPrincipals"))
                    {
                        var sid = dn.Split(',')[0].Substring(3);
                        if (dn.Contains("CN=S-1-5-21"))
                        {
                            var domain = _utils.SidToDomainName(sid);
                            if (domain == null)
                            {
                                Utils.Verbose($"Unable to resolve domain for FSP {dn}");
                                continue;
                            }

                            principal = _utils.UnknownSidTypeToDisplay(sid, domain, Props);
                        }
                        else
                        {
                            if (!MappedPrincipal.GetCommon(sid, out principal))
                            {
                                continue;
                            }

                            principal.PrincipalName = $"{principal.PrincipalName}@{principalDomainName}";
                        }
                    }
                    else
                    {
                        var objEntry = _utils
                                       .DoSearch("(objectclass=*)", SearchScope.Base, Props, Utils.ConvertDnToDomain(dn), dn)
                                       .DefaultIfEmpty(null).FirstOrDefault();

                        if (objEntry == null)
                        {
                            principal = null;
                        }
                        else
                        {
                            var resolvedObj = objEntry.ResolveAdEntry();
                            if (resolvedObj == null || resolvedObj.ObjectType == "domain")
                            {
                                principal = null;
                            }
                            else
                            {
                                _cache.AddMapValue(dn, resolvedObj.ObjectType, resolvedObj.BloodHoundDisplay);
                                principal = new MappedPrincipal
                                            (
                                    resolvedObj.BloodHoundDisplay,
                                    resolvedObj.ObjectType
                                            );
                            }
                        }
                    }
                }

                if (principal != null)
                {
                    fMembers.Add(new GroupMember
                    {
                        MemberName = principal.PrincipalName,
                        MemberType = principal.ObjectType
                    });
                }
            }

            u.Members = fMembers.Distinct().ToArray();
        }
Пример #3
0
        /// <summary>
        /// Processes an LDAP entry to resolve PrimaryGroup/MemberOf properties
        /// </summary>
        /// <param name="entry">LDAP entry</param>
        /// <param name="resolvedEntry">The resolved object with the name/type of the entry</param>
        /// <param name="domainSid">SID for the domain being enumerated. Used to resolve PrimaryGroupID</param>
        /// <returns></returns>
        public static IEnumerable <GroupMember> ProcessAdObject(SearchResultEntry entry, ResolvedEntry resolvedEntry, string domainSid)
        {
            var principalDisplayName = resolvedEntry.BloodHoundDisplay;
            var principalDomainName  = Utils.ConvertDnToDomain(entry.DistinguishedName);

            //If this object is a group, add it to our DN cache
            if (resolvedEntry.ObjectType.Equals("group"))
            {
                _cache.AddMapValue(entry.DistinguishedName, "group", principalDisplayName);
            }

            foreach (var dn in entry.GetPropArray("member"))
            {
                //Check our cache first
                if (!_cache.GetMapValueUnknownType(dn, out var principal))
                {
                    if (dn.Contains("ForeignSecurityPrincipals") && !dn.StartsWith("CN=S-1-5-21"))
                    {
                        if (dn.Contains("S-1-5-21"))
                        {
                            var sid = entry.GetProp("cn");
                            principal = _utils.UnknownSidTypeToDisplay(sid, _utils.SidToDomainName(sid), Props);
                        }
                        else
                        {
                            principal = null;
                        }
                    }
                    else
                    {
                        var objEntry = _utils
                                       .DoSearch("(objectclass=*)", SearchScope.Base, Props, Utils.ConvertDnToDomain(dn), dn)
                                       .DefaultIfEmpty(null).FirstOrDefault();

                        if (objEntry == null)
                        {
                            principal = null;
                        }
                        else
                        {
                            var resolvedObj = objEntry.ResolveAdEntry();

                            _cache.AddMapValue(dn, resolvedObj.ObjectType, resolvedObj.BloodHoundDisplay);
                            principal = new MappedPrincipal
                                        (
                                resolvedObj.BloodHoundDisplay,
                                resolvedObj.ObjectType
                                        );
                        }
                    }
                }



                if (principal != null)
                {
                    yield return(new GroupMember
                    {
                        AccountName = principal.PrincipalName,
                        GroupName = principalDisplayName,
                        ObjectType = principal.ObjectType
                    });
                }
            }

            var pgi = entry.GetProp("primarygroupid");

            if (pgi == null)
            {
                yield break;
            }

            var pgsid            = $"{domainSid}-{pgi}";
            var primaryGroupName = _utils.SidToDisplay(pgsid, principalDomainName, Props, "group");

            if (primaryGroupName != null)
            {
                yield return new GroupMember
                       {
                           AccountName = resolvedEntry.BloodHoundDisplay,
                           GroupName   = primaryGroupName,
                           ObjectType  = resolvedEntry.ObjectType
                       }
            }
            ;
        }
Пример #4
0
        /// <summary>
        /// Processes an LDAP entry to resolve PrimaryGroup/MemberOf properties
        /// </summary>
        /// <param name="entry">LDAP entry</param>
        /// <param name="resolvedEntry">The resolved object with the name/type of the entry</param>
        /// <param name="domainSid">SID for the domain being enumerated. Used to resolve PrimaryGroupID</param>
        /// <returns></returns>
        public static IEnumerable <GroupMember> ProcessAdObject(SearchResultEntry entry, ResolvedEntry resolvedEntry, string domainSid)
        {
            var principalDomainName  = Utils.ConvertDnToDomain(entry.DistinguishedName);
            var principalDisplayName = resolvedEntry.BloodHoundDisplay;
            var objectType           = resolvedEntry.ObjectType;

            //If this object is a group, add it to our DN cache
            if (objectType.Equals("group"))
            {
                _cache.AddMapValue(entry.DistinguishedName, "group", principalDisplayName);
            }

            foreach (var dn in entry.GetPropArray("memberof"))
            {
                //Check our cache first
                if (!_cache.GetMapValue(dn, "group", out var groupName))
                {
                    //Search for the object directly
                    var groupEntry = _utils
                                     .DoSearch("(objectclass=group)", SearchScope.Base, Props, Utils.ConvertDnToDomain(dn), dn)
                                     .DefaultIfEmpty(null).FirstOrDefault();

                    if (groupEntry == null)
                    {
                        //Our search didn't return anything so fallback
                        //Try convertadname first
                        groupName = ConvertAdName(dn, AdsTypes.AdsNameTypeDn, AdsTypes.AdsNameTypeNt4);

                        //If convertadname is null, just screw with the distinguishedname to get the group
                        groupName = groupName != null
                            ? groupName.Split('\\').Last()
                            : dn.Substring(0, dn.IndexOf(",", StringComparison.Ordinal)).Split('=').Last();
                    }
                    else
                    {
                        //We got an object back!
                        groupName = groupEntry.ResolveAdEntry().BloodHoundDisplay;
                    }

                    //If we got a group back, add it to the cache for later use
                    if (groupName != null)
                    {
                        _cache.AddMapValue(dn, "group", groupName);
                    }
                }

                //We got our group! Return it
                if (groupName != null)
                {
                    yield return new GroupMember
                           {
                               AccountName = principalDisplayName,
                               GroupName   = groupName,
                               ObjectType  = objectType
                           }
                }
                ;
            }

            var primaryGroupId = entry.GetProp("primarygroupid");

            if (primaryGroupId == null)
            {
                yield break;
            }

            //As far as I know you cant belong to a primary group of another domain
            var pgsid            = $"{domainSid}-{primaryGroupId}";
            var primaryGroupName = _utils.SidToDisplay(pgsid, principalDomainName, Props, "group");

            if (primaryGroupName != null)
            {
                yield return new GroupMember
                       {
                           AccountName = principalDisplayName,
                           GroupName   = primaryGroupName,
                           ObjectType  = objectType
                       }
            }
            ;
        }