예제 #1
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Computer obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled, unconstrained, trustedToAuth;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled       = (flags & UacFlags.AccountDisable) == 0;
                unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation;
                trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
            }
            else
            {
                unconstrained = false;
                enabled       = true;
                trustedToAuth = false;
            }

            var comps = new List <string>();

            if (trustedToAuth)
            {
                var delegates = entry.GetPropArray("msds-allowedToDelegateTo");
                obj.Properties.Add("allowedtodelegate", delegates);

                foreach (var d in delegates)
                {
                    var hname = d.Contains("/") ? d.Split('/')[1] : d;
                    hname = hname.Split(':')[0];
                    var resolvedHost = Utils.Instance.ResolveHost(hname);
                    if (resolvedHost.Contains("."))
                    {
                        comps.Add(resolvedHost.ToUpper());
                    }
                }
            }
            obj.AllowedToDelegate = comps.Distinct().ToArray();

            obj.Properties.Add("enabled", enabled);
            obj.Properties.Add("unconstraineddelegation", unconstrained);
            obj.Properties.Add("lastlogon", ConvertToUnixEpoch(entry.GetProp("lastlogon")));
            obj.Properties.Add("lastlogontimestamp", ConvertToUnixEpoch(entry.GetProp("lastlogontimestamp")));
            obj.Properties.Add("pwdlastset", ConvertToUnixEpoch(entry.GetProp("pwdlastset")));
            obj.Properties.Add("serviceprincipalnames", entry.GetPropArray("serviceprincipalname"));
            var os = entry.GetProp("operatingsystem");
            var sp = entry.GetProp("operatingsystemservicepack");

            if (sp != null)
            {
                os = $"{os} {sp}";
            }

            obj.Properties.Add("operatingsystem", os);
            obj.Properties.Add("description", entry.GetProp("description"));
        }
예제 #2
0
        internal static void GetSpnTargets(SearchResultEntry entry, ResolvedEntry resolved, ref User obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.SPNTargets))
            {
                return;
            }

            var spn             = entry.GetPropArray("serviceprincipalname");
            var resolvedTargets = new List <SPNTarget>();
            var domain          = Utils.ConvertDnToDomain(entry.DistinguishedName);

            foreach (var sp in spn)
            {
                if (sp.Contains("@"))
                {
                    continue;
                }

                if (sp.ToLower().Contains("mssqlsvc"))
                {
                    var    initial = sp.Split('/')[1];
                    string host;
                    int    port;
                    if (initial.Contains(':'))
                    {
                        var t = initial.Split(':');
                        host = t[0];
                        if (!int.TryParse(t[1], out port))
                        {
                            port = 1433;
                        }
                    }
                    else
                    {
                        host = initial;
                        port = 1433;
                    }

                    var resolvedHost = Utils.Instance.ResolveHost(host, domain);
                    if (!resolvedHost.Contains("."))
                    {
                        continue;
                    }

                    if (Utils.CheckSqlServer(resolvedHost, port))
                    {
                        resolvedTargets.Add(new SPNTarget
                        {
                            ComputerName = resolvedHost,
                            Port         = port,
                            Service      = "SQLAdmin"
                        });
                    }
                }
            }

            obj.SPNTargets = resolvedTargets.Distinct().ToArray();
        }
예제 #3
0
        public static UserProp GetUserProps(SearchResultEntry entry, ResolvedEntry resolved)
        {
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled = (flags & UacFlags.AccountDisable) == 0;
            }
            else
            {
                enabled = true;
            }
            var history          = entry.GetPropBytes("sidhistory");
            var lastlogon        = entry.GetProp("lastlogon");
            var pwdlastset       = entry.GetProp("pwdlastset");
            var spn              = entry.GetPropArray("serviceprincipalname");
            var displayName      = entry.GetProp("displayname");
            var hasSpn           = spn.Length != 0;
            var spnString        = string.Join("|", spn);
            var convertedlogon   = ConvertToUnixEpoch(lastlogon);
            var convertedlastset = ConvertToUnixEpoch(pwdlastset);
            var sid              = entry.GetSid();
            var sidhistory       = history != null ? new SecurityIdentifier(history, 0).Value : "";
            var mail             = entry.GetProp("mail");
            var domain           = resolved.BloodHoundDisplay.Split('@')[1].ToUpper();
            var title            = entry.GetProp("title");
            var homedir          = entry.GetProp("homeDirectory");

            return(new UserProp
            {
                AccountName = resolved.BloodHoundDisplay,
                Enabled = enabled,
                LastLogon = convertedlogon,
                ObjectSid = sid,
                PwdLastSet = convertedlastset,
                SidHistory = sidhistory,
                HasSpn = hasSpn,
                ServicePrincipalNames = spnString,
                DisplayName = displayName,
                Email = mail,
                Domain = domain,
                Title = title,
                HomeDirectory = homedir
            });
        }
예제 #4
0
        internal static ResolvedEntry ResolveAdEntry(this SearchResultEntry result)
        {
            var entry = new ResolvedEntry();

            var accountName       = result.GetProp("samaccountname");
            var distinguishedName = result.DistinguishedName;
            var accountType       = result.GetProp("samaccounttype");

            if (distinguishedName == null)
            {
                return(null);
            }

            var domainName = Utils.ConvertDnToDomain(distinguishedName);

            if (Groups.Contains(accountType))
            {
                entry.BloodHoundDisplay = $"{accountName}@{domainName}".ToUpper();
                entry.ObjectType        = "group";
                return(entry);
            }

            if (Users.Contains(accountType))
            {
                entry.BloodHoundDisplay = $"{accountName}@{domainName}".ToUpper();
                entry.ObjectType        = "user";
                return(entry);
            }

            if (Computers.Contains(accountType))
            {
                var shortName   = accountName?.TrimEnd('$');
                var dnshostname = result.GetProp("dnshostname");

                if (dnshostname == null)
                {
                    bool hostFound;
                    if (domainName.Equals(_primaryDomain, StringComparison.CurrentCultureIgnoreCase))
                    {
                        hostFound = DnsManager.HostExistsDns(shortName, out dnshostname);
                        if (!hostFound)
                        {
                            hostFound = DnsManager.HostExistsDns($"{shortName}.{domainName}", out dnshostname);
                        }
                    }
                    else
                    {
                        hostFound = DnsManager.HostExistsDns($"{shortName}.{domainName}", out dnshostname);
                        if (!hostFound)
                        {
                            hostFound = DnsManager.HostExistsDns(shortName, out dnshostname);
                        }
                    }

                    if (!hostFound)
                    {
                        return(null);
                    }
                }
                entry.BloodHoundDisplay      = dnshostname;
                entry.ObjectType             = "computer";
                entry.ComputerSamAccountName = shortName;
                return(entry);
            }



            if (accountType == null)
            {
                var objClass = result.GetPropArray("objectClass");
                if (objClass.Contains("groupPolicyContainer"))
                {
                    entry.BloodHoundDisplay = $"{result.GetProp("displayname")}@{domainName}";
                    entry.ObjectType        = "gpo";
                    return(entry);
                }

                if (objClass.Contains("organizationalUnit"))
                {
                    entry.BloodHoundDisplay = $"{result.GetProp("name")}@{domainName}";
                    entry.ObjectType        = "ou";
                    return(entry);
                }

                if (objClass.Contains("container"))
                {
                    entry.BloodHoundDisplay = domainName;
                    entry.ObjectType        = "container";
                    return(entry);
                }
            }
            else
            {
                if (accountType.Equals("805306370"))
                {
                    return(null);
                }
            }
            entry.BloodHoundDisplay = domainName;
            entry.ObjectType        = "domain";
            return(entry);
        }
예제 #5
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
                       }
            }
            ;
        }
예제 #6
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
                       }
            }
            ;
        }
예제 #7
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref User obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled, trustedToAuth;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled       = (flags & UacFlags.AccountDisable) == 0;
                trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
            }
            else
            {
                trustedToAuth = false;
                enabled       = true;
            }

            var comps = new List <string>();

            if (trustedToAuth)
            {
                var delegates = entry.GetPropArray("msds-allowedToDelegateTo");
                obj.Properties.Add("allowedtodelegate", delegates);

                foreach (var d in delegates)
                {
                    var hname = d.Contains("/") ? d.Split('/')[1] : d;
                    hname = hname.Split(':')[0];
                    var resolvedHost = Utils.Instance.ResolveHost(hname);
                    if (resolvedHost.Contains("."))
                    {
                        comps.Add(resolvedHost.ToUpper());
                    }
                }
            }
            obj.AllowedToDelegate = comps.Distinct().ToArray();

            obj.Properties.Add("enabled", enabled);
            //var history = entry.GetPropBytes("sidhistory");
            //obj.SidHistory = history != null ? new SecurityIdentifier(history, 0).Value : "";
            obj.Properties.Add("lastlogon", ConvertToUnixEpoch(entry.GetProp("lastlogon")));
            obj.Properties.Add("pwdlastset", ConvertToUnixEpoch(entry.GetProp("pwdlastset")));
            var spn = entry.GetPropArray("serviceprincipalname");

            obj.Properties.Add("serviceprincipalnames", spn);
            obj.Properties.Add("hasspn", spn.Length > 0);
            obj.Properties.Add("displayname", entry.GetProp("displayname"));
            obj.Properties.Add("email", entry.GetProp("mail"));
            obj.Properties.Add("title", entry.GetProp("title"));
            obj.Properties.Add("homedirectory", entry.GetProp("homedirectory"));
            obj.Properties.Add("description", entry.GetProp("description"));
            obj.Properties.Add("userpassword", entry.GetProp("userpassword"));
            var ac = entry.GetProp("admincount");

            if (ac != null)
            {
                var a = int.Parse(ac);
                obj.Properties.Add("admincount", a != 0);
            }
            else
            {
                obj.Properties.Add("admincount", false);
            }
        }
예제 #8
0
        internal static void GetProps(SearchResultEntry entry, ResolvedEntry resolved, ref Computer obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ObjectProps))
            {
                return;
            }
            var  uac = entry.GetProp("useraccountcontrol");
            bool enabled, unconstrained, trustedToAuth;

            if (int.TryParse(uac, out var flag))
            {
                var flags = (UacFlags)flag;
                enabled       = (flags & UacFlags.AccountDisable) == 0;
                unconstrained = (flags & UacFlags.TrustedForDelegation) == UacFlags.TrustedForDelegation;
                trustedToAuth = (flags & UacFlags.TrustedToAuthForDelegation) != 0;
            }
            else
            {
                unconstrained = false;
                enabled       = true;
                trustedToAuth = false;
            }

            var comps = new List <string>();

            if (trustedToAuth)
            {
                var delegates = entry.GetPropArray("msds-allowedToDelegateTo");
                obj.Properties.Add("allowedtodelegate", delegates);

                foreach (var d in delegates)
                {
                    var hname = d.Contains("/") ? d.Split('/')[1] : d;
                    hname = hname.Split(':')[0];
                    var resolvedHost = Utils.Instance.ResolveHost(hname);
                    if (resolvedHost.Contains("."))
                    {
                        comps.Add(resolvedHost.ToUpper());
                    }
                }
            }
            obj.AllowedToDelegate = comps.Distinct().ToArray();

            var allowedToAct = entry.GetPropBytes("msDS-AllowedToActOnBehalfOfOtherIdentity");

            if (allowedToAct != null)
            {
                var principals = new List <LocalMember>();
                var sd         = new ActiveDirectorySecurity();
                sd.SetSecurityDescriptorBinaryForm(allowedToAct, AccessControlSections.Access);
                var utils = Utils.Instance;
                foreach (ActiveDirectoryAccessRule rule in sd.GetAccessRules(true, true, typeof(SecurityIdentifier)))
                {
                    var sid    = rule.IdentityReference.Value;
                    var domain = utils.SidToDomainName(sid) ?? Utils.ConvertDnToDomain(entry.DistinguishedName);
                    if (!MappedPrincipal.GetCommon(sid, out var principal))
                    {
                        principal = utils.UnknownSidTypeToDisplay(sid, domain, Props);
                    }
                    else
                    {
                        if (sid == "S-1-5-9")
                        {
                            var dObj = utils.GetForest(domain);
                            var d    = dObj == null ? domain : dObj.RootDomain.Name;
                            principal.PrincipalName = $"ENTERPRISE DOMAIN CONTROLLERS@{d}".ToUpper();
                        }
                        else
                        {
                            principal.PrincipalName = $"{principal.PrincipalName}@{domain}".ToUpper();
                        }
                    }

                    if (principal == null)
                    {
                        continue;
                    }

                    principals.Add(new LocalMember
                    {
                        Name = principal.PrincipalName,
                        Type = principal.ObjectType
                    });
                }

                obj.AllowedToAct = principals.ToArray();
            }

            obj.Properties.Add("enabled", enabled);
            obj.Properties.Add("unconstraineddelegation", unconstrained);
            obj.Properties.Add("lastlogon", ConvertToUnixEpoch(entry.GetProp("lastlogon")));
            obj.Properties.Add("lastlogontimestamp", ConvertToUnixEpoch(entry.GetProp("lastlogontimestamp")));
            obj.Properties.Add("pwdlastset", ConvertToUnixEpoch(entry.GetProp("pwdlastset")));
            obj.Properties.Add("serviceprincipalnames", entry.GetPropArray("serviceprincipalname"));
            var os = entry.GetProp("operatingsystem");
            var sp = entry.GetProp("operatingsystemservicepack");

            if (sp != null)
            {
                os = $"{os} {sp}";
            }

            obj.Properties.Add("operatingsystem", os);
            obj.Properties.Add("description", entry.GetProp("description"));
        }
예제 #9
0
        internal static LdapWrapper FindLdapType(SearchResultEntry searchResultEntry)
        {
            //Look for a null DN first. Not sure why this would happen.
            var distinguishedName = searchResultEntry.DistinguishedName;

            if (distinguishedName == null)
            {
                return(null);
            }

            var accountName    = searchResultEntry.GetProp("samaccountname");
            var samAccountType = searchResultEntry.GetProp("samaccounttype");
            var accountDomain  = Helpers.DistinguishedNameToDomain(distinguishedName);
            var objectSid      = searchResultEntry.GetSid();
            var objectType     = LdapTypeEnum.Unknown;

            LdapWrapper wrapper;

            //Lets see if its a "common" principal
            if (CommonPrincipal.GetCommonSid(objectSid, out var commonPrincipal))
            {
                accountName = commonPrincipal.Name;
                objectType  = commonPrincipal.Type;
            }
            else
            {
                //Its not a common principal. Lets use properties to figure out what it actually is
                if (samAccountType != null)
                {
                    if (samAccountType == "805306370")
                    {
                        return(null);
                    }

                    objectType = Helpers.SamAccountTypeToType(samAccountType);
                }
                else
                {
                    var objectClasses = searchResultEntry.GetPropArray("objectClass");
                    if (objectClasses == null)
                    {
                        objectType = LdapTypeEnum.Unknown;
                    }
                    else if (objectClasses.Contains("groupPolicyContainer"))
                    {
                        objectType = LdapTypeEnum.GPO;
                    }
                    else if (objectClasses.Contains("organizationalUnit"))
                    {
                        objectType = LdapTypeEnum.OU;
                    }
                    else if (objectClasses.Contains("domain"))
                    {
                        objectType = LdapTypeEnum.Domain;
                    }
                }
            }

            //Depending on the object type, create the appropriate wrapper object
            switch (objectType)
            {
            case LdapTypeEnum.Computer:
                accountName = accountName?.TrimEnd('$');
                wrapper     = new Computer(searchResultEntry)
                {
                    DisplayName = $"{accountName}.{accountDomain}"
                };
                break;

            case LdapTypeEnum.User:
                wrapper = new User(searchResultEntry)
                {
                    DisplayName = $"{accountName}@{accountDomain}"
                };
                break;

            case LdapTypeEnum.Group:
                wrapper = new Group(searchResultEntry)
                {
                    DisplayName = $"{accountName}@{accountDomain}"
                };
                break;

            case LdapTypeEnum.GPO:
                accountName = searchResultEntry.GetProp("displayname");
                wrapper     = new GPO(searchResultEntry)
                {
                    DisplayName = $"{accountName}@{accountDomain}"
                };
                break;

            case LdapTypeEnum.OU:
                accountName = searchResultEntry.GetProp("name");
                wrapper     = new OU(searchResultEntry)
                {
                    DisplayName = $"{accountName}@{accountDomain}"
                };
                break;

            case LdapTypeEnum.Domain:
                wrapper = new Domain(searchResultEntry)
                {
                    DisplayName = accountDomain
                };
                break;

            case LdapTypeEnum.Unknown:
                wrapper = null;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            //Set the DN/SID for the wrapper going forward
            if (wrapper == null)
            {
                return(wrapper);
            }
            wrapper.DistinguishedName  = distinguishedName;
            wrapper.SecurityIdentifier = objectSid;

            //Return our wrapper for the next step in the pipeline
            return(wrapper);
        }
예제 #10
0
        internal static ResolvedEntry ResolveAdEntry(this SearchResultEntry result, bool bypassDns = false)
        {
            var entry = new ResolvedEntry();

            var accountName       = result.GetProp("samaccountname");
            var distinguishedName = result.DistinguishedName;
            var accountType       = result.GetProp("samaccounttype");

            if (distinguishedName == null)
            {
                return(null);
            }

            var domainName = Utils.ConvertDnToDomain(distinguishedName);

            if (MappedPrincipal.GetCommon(result.GetSid(), out var temp))
            {
                return(new ResolvedEntry
                {
                    IngestCacheDisplay = $"{temp.PrincipalName}@{domainName}".ToUpper(),
                    ObjectType = temp.ObjectType
                });
            }

            if (Groups.Contains(accountType))
            {
                entry.IngestCacheDisplay = $"{accountName}@{domainName}".ToUpper();
                entry.ObjectType         = "group";
                return(entry);
            }

            if (Users.Contains(accountType))
            {
                entry.IngestCacheDisplay = $"{accountName}@{domainName}".ToUpper();
                entry.ObjectType         = "user";
                return(entry);
            }

            if (Computers.Contains(accountType))
            {
                var shortName   = accountName?.TrimEnd('$');
                var dnshostname = result.GetProp("dnshostname");
                if (dnshostname == null)
                {
                    var domain = Utils.ConvertDnToDomain(result.DistinguishedName);
                    dnshostname = $"{shortName}.{domain}".ToUpper();
                }

                entry.IngestCacheDisplay     = dnshostname;
                entry.ObjectType             = "computer";
                entry.ComputerSamAccountName = shortName;
                return(entry);
            }

            if (accountType == null)
            {
                var objClass = result.GetPropArray("objectClass");
                if (objClass.Contains("groupPolicyContainer"))
                {
                    entry.IngestCacheDisplay = $"{result.GetProp("displayname")}@{domainName}";
                    entry.ObjectType         = "gpo";
                    return(entry);
                }

                if (objClass.Contains("organizationalUnit"))
                {
                    entry.IngestCacheDisplay = $"{result.GetProp("name")}@{domainName}";
                    entry.ObjectType         = "ou";
                    return(entry);
                }

                if (objClass.Contains("container"))
                {
                    entry.IngestCacheDisplay = domainName;
                    entry.ObjectType         = "container";
                    return(entry);
                }
            }
            else
            {
                if (accountType.Equals("805306370"))
                {
                    return(null);
                }
            }
            entry.IngestCacheDisplay = domainName;
            entry.ObjectType         = "domain";
            return(entry);
        }
예제 #11
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();
        }
예제 #12
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
                       }
            }
            ;
        }