예제 #1
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Domain u)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            //Convert the ntsecuritydescriptor bytes to a .net object
            var descriptor = new RawSecurityDescriptor(ntSecurityDescriptor, 0);

            //Grab the DACL
            var rawAcl = descriptor.DiscretionaryAcl;
            //Grab the Owner
            var ownerSid = descriptor.Owner.ToString();

            //Determine the owner of the object. Start by checking if we've already determined this is null
            if (!_nullSids.TryGetValue(ownerSid, out _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(ownerSid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(ownerSid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(ownerSid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //Filter out the Local System principal which pretty much every entry has
                if (owner != null && !owner.PrincipalName.Contains("LOCAL SYSTEM") && !owner.PrincipalName.Contains("CREATOR OWNER"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "Owner",
                        PrincipalName = owner.PrincipalName,
                        PrincipalType = owner.ObjectType
                    });
                }
                else
                {
                    //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                    _nullSids.TryAdd(ownerSid, new byte());
                }
            }

            foreach (var genericAce in rawAcl)
            {
                var qAce = genericAce as QualifiedAce;
                if (qAce == null)
                {
                    continue;
                }

                if (!qAce.AceQualifier.Equals(AceQualifier.AccessAllowed))
                {
                    continue;
                }

                var objectSid = qAce.SecurityIdentifier.ToString();
                if (_nullSids.TryGetValue(objectSid, out _))
                {
                    continue;
                }

                //Check if its a common sid
                if (!MappedPrincipal.GetCommon(objectSid, out var mappedPrincipal))
                {
                    //If not common, lets resolve it normally
                    var objectDomain =
                        _utils.SidToDomainName(objectSid) ??
                        domainName;
                    mappedPrincipal = _utils.UnknownSidTypeToDisplay(objectSid, objectDomain, Props);
                    if (mappedPrincipal == null)
                    {
                        _nullSids.TryAdd(objectSid, new byte());
                        continue;
                    }
                }
                else
                {
                    if (mappedPrincipal.PrincipalName == "ENTERPRISE DOMAIN CONTROLLERS")
                    {
                        var d = _utils.GetForest(domainName).RootDomain.Name;
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{d}".ToUpper();
                    }
                    else
                    {
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{domainName}".ToUpper();
                    }
                }

                if (mappedPrincipal.PrincipalName.Contains("LOCAL SYSTEM") || mappedPrincipal.PrincipalName.Contains("CREATOR OWNER"))
                {
                    continue;
                }

                //Convert our right to an ActiveDirectoryRight enum object, and then to a string
                var adRight       = (ActiveDirectoryRights)Enum.ToObject(typeof(ActiveDirectoryRights), qAce.AccessMask);
                var adRightString = adRight.ToString();

                //Get the ACE for our right
                var ace  = qAce as ObjectAce;
                var guid = ace != null?ace.ObjectAceType.ToString() : "";

                var inheritedObjectType = ace != null?ace.InheritedObjectAceType.ToString() : "00000000-0000-0000-0000-000000000000";

                var isInherited = inheritedObjectType == "00000000-0000-0000-0000-000000000000" ||
                                  inheritedObjectType == "19195a5a-6da0-11d0-afd3-00c04fd930c9";

                var flags = ace == null ? AceFlags.None : ace.AceFlags;
                if ((flags & AceFlags.InheritOnly) != 0)
                {
                    isInherited = false;
                }

                //Special case used for example by Exchange: the ACE is inherited but also applies to the object it is set on
                // this is verified by looking if this ACE is not inherited, and is not an inherit-only ACE
                if (!isInherited && (flags & AceFlags.InheritOnly) != AceFlags.InheritOnly && (flags & AceFlags.Inherited) != AceFlags.Inherited)
                {
                    //If these conditions hold the ACE applies to this object anyway
                    isInherited = true;
                }

                if (!isInherited)
                {
                    continue;
                }

                var toContinue = false;

                //Interesting Group ACEs - GenericAll, WriteDacl, WriteOwner, GenericWrite, AddMember
                toContinue |= (adRightString.Contains("WriteDacl") || adRightString.Contains("WriteOwner"));
                if (adRightString.Contains("GenericAll"))
                {
                    toContinue |= ("00000000-0000-0000-0000-000000000000".Equals(guid) || guid.Equals("") || toContinue);
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    toContinue |= (guid.Equals("00000000-0000-0000-0000-000000000000") ||
                                   guid.Equals("1131f6aa-9c07-11d1-f79f-00c04fc2dcd2") ||
                                   guid.Equals("1131f6ad-9c07-11d1-f79f-00c04fc2dcd2") || guid.Equals("") ||
                                   toContinue);
                }

                if (!toContinue)
                {
                    continue;
                }


                if (adRightString.Contains("GenericAll"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "GenericAll"
                    });
                }

                if (adRightString.Contains("WriteOwner"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteOwner"
                    });
                }

                if (adRightString.Contains("WriteDacl"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteDacl"
                    });
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    if (guid.Equals("1131f6aa-9c07-11d1-f79f-00c04fc2dcd2"))
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChanges",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ExtendedRight"
                        });
                    }
                    else if (guid.Equals("1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"))
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChangesAll",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ExtendedRight"
                        });
                    }
                    else
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "All",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ExtendedRight"
                        });
                    }
                }
            }

            u.Aces = aces.Distinct().ToArray();
        }
예제 #2
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Computer g)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            //We only care about computers if they have LAPS installed
            if (entry.GetProp("ms-mcs-admpwdexpirationtime") == null)
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            //Convert the ntsecuritydescriptor bytes to a .net object
            var descriptor = new RawSecurityDescriptor(ntSecurityDescriptor, 0);

            //Grab the DACL
            var rawAcl = descriptor.DiscretionaryAcl;
            //Grab the Owner
            var ownerSid = descriptor.Owner.ToString();

            //Determine the owner of the object. Start by checking if we've already determined this is null
            if (!_nullSids.TryGetValue(ownerSid, out _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(ownerSid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(ownerSid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(ownerSid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //Filter out the Local System principal which pretty much every entry has
                if (owner != null && !owner.PrincipalName.Contains("LOCAL SYSTEM") && !owner.PrincipalName.Contains("CREATOR OWNER"))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "Owner",
                        PrincipalName = owner.PrincipalName,
                        PrincipalType = owner.ObjectType
                    });
                }
                else
                {
                    //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                    _nullSids.TryAdd(ownerSid, new byte());
                }
            }

            foreach (var genericAce in rawAcl)
            {
                var qAce = genericAce as QualifiedAce;
                if (qAce == null)
                {
                    continue;
                }

                var objectSid = qAce.SecurityIdentifier.ToString();
                if (_nullSids.TryGetValue(objectSid, out _))
                {
                    continue;
                }

                //Check if its a common sid
                if (!MappedPrincipal.GetCommon(objectSid, out var mappedPrincipal))
                {
                    //If not common, lets resolve it normally
                    var objectDomain =
                        _utils.SidToDomainName(objectSid) ??
                        domainName;
                    mappedPrincipal = _utils.UnknownSidTypeToDisplay(objectSid, objectDomain, Props);
                    if (mappedPrincipal == null)
                    {
                        _nullSids.TryAdd(objectSid, new byte());
                        continue;
                    }
                }
                else
                {
                    if (mappedPrincipal.PrincipalName == "ENTERPRISE DOMAIN CONTROLLERS")
                    {
                        var d = _utils.GetForest(domainName).RootDomain.Name;
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{d}".ToUpper();
                    }
                    else
                    {
                        mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{domainName}".ToUpper();
                    }
                }

                if (mappedPrincipal.PrincipalName.Contains("LOCAL SYSTEM") || mappedPrincipal.PrincipalName.Contains("CREATOR OWNER"))
                {
                    continue;
                }

                //Convert our right to an ActiveDirectoryRight enum object, and then to a string
                var adRight       = (ActiveDirectoryRights)Enum.ToObject(typeof(ActiveDirectoryRights), qAce.AccessMask);
                var adRightString = adRight.ToString();

                //Get the ACE for our right
                var ace  = qAce as ObjectAce;
                var guid = ace != null?ace.ObjectAceType.ToString() : "";

                var inheritedObjectType = ace != null?ace.InheritedObjectAceType.ToString() : "00000000-0000-0000-0000-000000000000";

                var isInherited = inheritedObjectType == "00000000-0000-0000-0000-000000000000" ||
                                  inheritedObjectType == "bf967a86-0de6-11d0-a285-00aa003049e2";

                if (!isInherited && !((ace.AceFlags & AceFlags.InheritOnly) == AceFlags.InheritOnly) && (ace.AceFlags & AceFlags.Inherited) != AceFlags.Inherited)
                {
                    //If these conditions hold the ACE applies to this object anyway
                    isInherited = true;
                }

                if (!isInherited)
                {
                    continue;
                }

                var toContinue = false;


                _guidMap.TryGetValue(guid, out var mappedGuid);

                //Interesting Computer ACEs - GenericAll, WriteDacl, WriteOwner, ExtendedRight
                toContinue |= adRightString.Contains("WriteDacl") ||
                              adRightString.Contains("WriteOwner");

                if (adRightString.Contains("GenericAll"))
                {
                    toContinue |= "00000000-0000-0000-0000-000000000000".Equals(guid) || guid.Equals("") || toContinue;
                    toContinue |= mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd" || toContinue;
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    toContinue |= guid.Equals("00000000-0000-0000-0000-000000000000") || guid.Equals("") || toContinue;
                    toContinue |= mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd" || toContinue;
                }

                if (!toContinue)
                {
                    continue;
                }

                if ((adRight & ActiveDirectoryRights.GenericAll) != ActiveDirectoryRights.GenericAll)
                {
                    if (mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ReadLAPSPassword"
                        });
                    }
                    else
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "GenericAll"
                        });
                    }
                }

                if ((adRight & ActiveDirectoryRights.WriteOwner) != 0)
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteOwner"
                    });
                }

                if ((adRight & ActiveDirectoryRights.WriteDacl) != 0)
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        RightName     = "WriteDacl"
                    });
                }

                if ((adRight & ActiveDirectoryRights.ExtendedRight) != 0)
                {
                    if (mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ReadLAPSPassword"
                        });
                    }
                    else
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "All",
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            RightName     = "ExtendedRight"
                        });
                    }
                }
            }

            g.Aces = aces.Distinct().ToArray();
        }
예제 #3
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, Utils.ConvertDnToDomain(entry.DistinguishedName));
                    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"));
        }
예제 #4
0
        /// <summary>
        /// Processes the ACL entries for an AD object
        /// </summary>
        /// <param name="entry">LDAP entry to process</param>
        /// <param name="domainName">Domain name the entry belongs too</param>
        /// <returns>A list of ACL objects for the entry</returns>
        public static IEnumerable <ACL> ProcessAdObject(SearchResultEntry entry, string domainName)
        {
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                yield break;
            }

            //Convert the ntsecuritydescriptor bytes to a .net object
            var descriptor = new RawSecurityDescriptor(ntSecurityDescriptor, 0);

            //Grab the DACL
            var rawAcl = descriptor.DiscretionaryAcl;
            //Grab the Owner
            var ownerSid = descriptor.Owner.ToString();

            //Resolve the entry name/type
            var resolvedEntry = entry.ResolveAdEntry();

            //If our name is null, we dont know what the principal is
            if (resolvedEntry == null)
            {
                yield break;
            }

            var entryDisplayName = resolvedEntry.BloodHoundDisplay;
            var entryType        = resolvedEntry.ObjectType;

            //Determine the owner of the object. Start by checking if we've already determined this is null
            if (!_nullSids.TryGetValue(ownerSid, out byte _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(ownerSid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(ownerSid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(ownerSid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //Filter out the Local System principal which pretty much every entry has
                if (owner != null && !owner.PrincipalName.Contains("Local System"))
                {
                    yield return(new ACL
                    {
                        PrincipalName = $"{owner.PrincipalName}",
                        PrincipalType = owner.ObjectType,
                        Inherited = false,
                        RightName = "Owner",
                        AceType = "",
                        ObjectName = entryDisplayName,
                        ObjectType = entryType,
                        Qualifier = "AccessAllowed"
                    });
                }
                else
                {
                    //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                    _nullSids.TryAdd(ownerSid, new byte());
                }
            }

            //Loop over the actual entries in the DACL
            foreach (var genericAce in rawAcl)
            {
                var qAce      = (QualifiedAce)genericAce;
                var objectSid = qAce.SecurityIdentifier.ToString();

                //If this is something we already resolved to null, just keep on moving
                if (_nullSids.TryGetValue(objectSid, out byte _))
                {
                    continue;
                }

                //Check if its a common sid
                if (!MappedPrincipal.GetCommon(objectSid, out var mappedPrincipal))
                {
                    //If not common, lets resolve it normally
                    var objectDomain =
                        _utils.SidToDomainName(objectSid) ??
                        domainName;
                    mappedPrincipal = _utils.UnknownSidTypeToDisplay(objectSid, objectDomain, Props);
                    if (mappedPrincipal == null)
                    {
                        _nullSids.TryAdd(objectSid, new byte());
                        continue;
                    }
                }
                else
                {
                    mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{domainName}";
                }

                if (mappedPrincipal.PrincipalName.Contains("Local System"))
                {
                    continue;
                }

                //We have a principal and we've successfully resolved the object. Lets process stuff!

                //Convert our right to an ActiveDirectoryRight enum object, and then to a string
                var adRight       = (ActiveDirectoryRights)Enum.ToObject(typeof(ActiveDirectoryRights), qAce.AccessMask);
                var adRightString = adRight.ToString();

                //Get the ACE for our right
                var ace  = qAce as ObjectAce;
                var guid = ace != null?ace.ObjectAceType.ToString() : "";

                var toContinue = false;

                //Figure out if we need more processing by matching the right name + guid together
                toContinue |= (adRightString.Contains("WriteDacl") || adRightString.Contains("WriteOwner"));
                if (adRightString.Contains("GenericWrite") || adRightString.Contains("GenericAll"))
                {
                    toContinue |= ("00000000-0000-0000-0000-000000000000".Equals(guid) || guid.Equals("") || toContinue);
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    toContinue |= (guid.Equals("00000000-0000-0000-0000-000000000000") || guid.Equals("") || guid.Equals("00299570-246d-11d0-a768-00aa006e0529") || toContinue);

                    //DCSync rights
                    toContinue |= (guid.Equals("1131f6aa-9c07-11d1-f79f-00c04fc2dcd2") || guid.Equals("1131f6ad-9c07-11d1-f79f-00c04fc2dcd2") || toContinue);
                }

                if (adRightString.Contains("WriteProperty"))
                {
                    toContinue |= (guid.Equals("00000000-0000-0000-0000-000000000000") || guid.Equals("bf9679c0-0de6-11d0-a285-00aa003049e2") || guid.Equals("bf9679a8-0de6-11d0-a285-00aa003049e2") || toContinue);
                }

                if (!toContinue)
                {
                    continue;
                }

                string aceType = null;
                if (adRightString.Contains("ExtendedRight"))
                {
                    switch (guid)
                    {
                    case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2":
                        aceType = "DS-Replication-Get-Changes";
                        break;

                    case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2":
                        aceType = "DS-Replication-Get-Changes-All";
                        break;

                    default:
                        aceType = "All";
                        break;
                    }
                }

                //If we have either of the DCSync rights, store it in a temporary object and continue.
                //We need both rights for either right to mean anything to us
                if (aceType != null && entryType.Equals("domain") && (aceType.Equals("DS-Replication-Get-Changes-All") ||
                                                                      aceType.Equals("DS-Replication-Get-Changes")))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    if (aceType.Contains("-All"))
                    {
                        sync.GetChangesAll = true;
                    }
                    else
                    {
                        sync.GetChanges = true;
                    }

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                    continue;
                }

                if (aceType != null && entryType.Equals("domain") && aceType.Equals("All"))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    sync.GetChangesAll = true;
                    sync.GetChanges    = true;

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                }

                if (aceType != null && entryType.Equals("domain") && adRightString.Contains("GenericAll"))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    sync.GetChangesAll = true;
                    sync.GetChanges    = true;

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                }

                //Return ACL objects based on rights + guid combos

                if (adRightString.Contains("GenericAll"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "GenericAll",
                        Qualifier = qAce.AceQualifier.ToString()
                    });
                }

                if (adRightString.Contains("GenericWrite"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "GenericWrite",
                        Qualifier = qAce.AceQualifier.ToString()
                    });
                }

                if (adRightString.Contains("WriteOwner"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "WriteOwner",
                        Qualifier = qAce.AceQualifier.ToString()
                    });
                }

                if (adRightString.Contains("WriteDacl"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "WriteDacl",
                        Qualifier = qAce.AceQualifier.ToString()
                    });
                }

                if (adRightString.Contains("WriteProperty"))
                {
                    if (guid.Equals("bf9679c0-0de6-11d0-a285-00aa003049e2"))
                    {
                        yield return(new ACL
                        {
                            AceType = "Member",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "WriteProperty",
                            Qualifier = qAce.AceQualifier.ToString()
                        });
                    }
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    if (guid.Equals("00299570-246d-11d0-a768-00aa006e0529"))
                    {
                        yield return(new ACL
                        {
                            AceType = "User-Force-Change-Password",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "ExtendedRight",
                            Qualifier = qAce.AceQualifier.ToString()
                        });
                    }
                    else
                    {
                        yield return(new ACL
                        {
                            AceType = "All",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "ExtendedRight",
                            Qualifier = qAce.AceQualifier.ToString()
                        });
                    }
                }
            }
        }
예제 #5
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Computer obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            var newDescriptor = new ActiveDirectorySecurity();

            newDescriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
            var owner = GetAclOwner(newDescriptor, domainName);

            if (owner != null)
            {
                aces.Add(new ACL
                {
                    AceType       = "",
                    RightName     = "Owner",
                    PrincipalName = owner.PrincipalName,
                    PrincipalType = owner.ObjectType
                });
            }


            foreach (ActiveDirectoryAccessRule ace in newDescriptor.GetAccessRules(true, true, typeof(SecurityIdentifier)))
            {
                //Ignore null aces
                if (ace == null)
                {
                    continue;
                }

                //Ignore Deny aces
                if (!ace.AccessControlType.Equals(AccessControlType.Allow))
                {
                    continue;
                }

                //Resolve the principal in the ACE
                var principal = GetAcePrincipal(ace, domainName);

                //If its null, we don't care so move on
                if (principal == null)
                {
                    continue;
                }

                //Check if our ACE applies through inheritance rules
                if (!CheckAceInheritanceRules(ace, resolved.ObjectType))
                {
                    continue;
                }

                //Interesting Computer ACEs - GenericAll, WriteDacl, GenericWrite, WriteProperty (AllowedToAct), WriteOwner, ExtendedRight (LAPS)
                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();

                _guidMap.TryGetValue(objectAceType, out var mappedGuid);

                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericAll",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "ReadLAPSPassword",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    //GenericAll includes every other flag, so continue here so we don't duplicate privs
                    continue;
                }

                if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) ||
                    rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                {
                    //GenericWrite encapsulates WriteProperty
                    if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) &&
                        (objectAceType == AllGuid || objectAceType == ""))
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericWrite",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                    {
                        if (objectAceType == AllGuid || objectAceType == "")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "",
                                RightName     = "GenericWrite",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                        else if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AllowedToAct",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType,
                                RightName     = "WriteProperty"
                            });
                        }
                    }
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteOwner",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (entry.GetProp("ms-mcs-admpwdexpirationtime") != null)
                    {
                        if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "",
                                RightName     = "ReadLAPSPassword",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                        else if (objectAceType == AllGuid || objectAceType == "")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                RightName     = "ExtendedRight",
                                PrincipalName = principal.PrincipalName,
                                PrincipalType = principal.ObjectType
                            });
                        }
                    }
                }
            }

            obj.Aces = aces.Distinct().ToArray();
        }
예제 #6
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Domain obj)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.ACL))
            {
                return;
            }

            var aces = new List <ACL>();
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                return;
            }

            var domainName = Utils.ConvertDnToDomain(entry.DistinguishedName);

            var newDescriptor = new ActiveDirectorySecurity();

            newDescriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
            var owner = GetAclOwner(newDescriptor, domainName);

            if (owner != null)
            {
                aces.Add(new ACL
                {
                    AceType       = "",
                    RightName     = "Owner",
                    PrincipalName = owner.PrincipalName,
                    PrincipalType = owner.ObjectType
                });
            }

            foreach (ActiveDirectoryAccessRule ace in newDescriptor.GetAccessRules(true, true, typeof(SecurityIdentifier)))
            {
                //Ignore null aces
                if (ace == null)
                {
                    continue;
                }

                //Ignore Deny aces
                if (!ace.AccessControlType.Equals(AccessControlType.Allow))
                {
                    continue;
                }

                //Resolve the principal in the ACE
                var principal = GetAcePrincipal(ace, domainName);

                //If its null, we don't care so move on
                if (principal == null)
                {
                    continue;
                }

                //Check if our ACE applies through inheritance rules
                if (!CheckAceInheritanceRules(ace, resolved.ObjectType))
                {
                    continue;
                }

                //Interesting Domain ACEs - GenericAll, WriteDacl, WriteOwner, Replication Rights, AllExtendedRights
                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();

                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericAll",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    //GenericAll includes every other flag, so continue here so we don't duplicate privs
                    continue;
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        AceType       = "",
                        RightName     = "WriteOwner",
                        PrincipalName = principal.PrincipalName,
                        PrincipalType = principal.ObjectType
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (objectAceType == "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChanges",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (objectAceType == "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "GetChangesAll",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                    else if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "All",
                            RightName     = "ExtendedRight",
                            PrincipalName = principal.PrincipalName,
                            PrincipalType = principal.ObjectType
                        });
                    }
                }
            }

            obj.Aces = aces.Distinct().ToArray();
        }
예제 #7
0
        /// <summary>
        /// Processes the ACL entries for an AD object
        /// </summary>
        /// <param name="entry">LDAP entry to process</param>
        /// <param name="domainName">Domain name the entry belongs too</param>
        /// <returns>A list of ACL objects for the entry</returns>
        public static IEnumerable <ACL> ProcessAdObject(SearchResultEntry entry, string domainName)
        {
            var ntSecurityDescriptor = entry.GetPropBytes("ntsecuritydescriptor");

            //If the ntsecuritydescriptor is null, no point in continuing
            //I'm still not entirely sure what causes this, but it can happen
            if (ntSecurityDescriptor == null)
            {
                yield break;
            }

            //Convert the ntsecuritydescriptor bytes to a .net object
            var descriptor = new RawSecurityDescriptor(ntSecurityDescriptor, 0);

            //Grab the DACL
            var rawAcl = descriptor.DiscretionaryAcl;
            //Grab the Owner
            var ownerSid = descriptor.Owner.ToString();

            //Resolve the entry name/type
            var resolvedEntry = entry.ResolveAdEntry();

            //If our name is null, we dont know what the principal is
            if (resolvedEntry == null)
            {
                yield break;
            }

            var    entryDisplayName = resolvedEntry.BloodHoundDisplay;
            var    entryType        = resolvedEntry.ObjectType;
            string entryGuid;

            if (entryType.Equals("gpo"))
            {
                var n = entry.GetProp("name").ToUpper();
                entryGuid = n.Substring(1, n.Length - 2);
            }
            else
            {
                entryGuid = "";
            }

            //We have no exploitable paths for Computer, so just ignore them
            if (entryType.Equals("computer"))
            {
                yield break;
            }

            //Determine the owner of the object. Start by checking if we've already determined this is null
            if (!_nullSids.TryGetValue(ownerSid, out byte _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(ownerSid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(ownerSid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(ownerSid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //Filter out the Local System principal which pretty much every entry has
                if (owner != null && !owner.PrincipalName.Contains("Local System"))
                {
                    yield return(new ACL
                    {
                        PrincipalName = owner.PrincipalName,
                        PrincipalType = owner.ObjectType,
                        Inherited = false,
                        RightName = "Owner",
                        AceType = "",
                        ObjectName = entryDisplayName,
                        ObjectType = entryType,
                        Qualifier = "AccessAllowed",
                        ObjectGuid = entryGuid
                    });
                }
                else
                {
                    //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                    _nullSids.TryAdd(ownerSid, new byte());
                }
            }

            //Loop over the actual entries in the DACL
            foreach (var genericAce in rawAcl)
            {
                var qAce      = (QualifiedAce)genericAce;
                var objectSid = qAce.SecurityIdentifier.ToString();

                //If this is something we already resolved to null, just keep on moving
                if (_nullSids.TryGetValue(objectSid, out byte _))
                {
                    continue;
                }

                //Check if its a common sid
                if (!MappedPrincipal.GetCommon(objectSid, out var mappedPrincipal))
                {
                    //If not common, lets resolve it normally
                    var objectDomain =
                        _utils.SidToDomainName(objectSid) ??
                        domainName;
                    mappedPrincipal = _utils.UnknownSidTypeToDisplay(objectSid, objectDomain, Props);
                    if (mappedPrincipal == null)
                    {
                        _nullSids.TryAdd(objectSid, new byte());
                        continue;
                    }
                }
                else
                {
                    mappedPrincipal.PrincipalName = $"{mappedPrincipal.PrincipalName}@{domainName}";
                }

                //bf967a86-0de6-11d0-a285-00aa003049e2 - Computer
                //bf967aba-0de6-11d0-a285-00aa003049e2 - User
                //bf967a9c-0de6-11d0-a285-00aa003049e2 - Group
                //19195a5a-6da0-11d0-afd3-00c04fd930c9 - Domain
                //f30e3bc2-9ff0-11d1-b603-0000f80367c1 - GPC

                if (mappedPrincipal.PrincipalName.Contains("Local System"))
                {
                    continue;
                }

                //We have a principal and we've successfully resolved the object. Lets process stuff!

                //Convert our right to an ActiveDirectoryRight enum object, and then to a string
                var adRight       = (ActiveDirectoryRights)Enum.ToObject(typeof(ActiveDirectoryRights), qAce.AccessMask);
                var adRightString = adRight.ToString();

                //Get the ACE for our right
                var ace  = qAce as ObjectAce;
                var guid = ace != null?ace.ObjectAceType.ToString() : "";

                var toContinue = false;

                //Figure out if we need more processing by matching the right name + guid together
                toContinue |= (adRightString.Contains("WriteDacl") || adRightString.Contains("WriteOwner"));
                if (adRightString.Contains("GenericWrite") || adRightString.Contains("GenericAll"))
                {
                    toContinue |= ("00000000-0000-0000-0000-000000000000".Equals(guid) || guid.Equals("") || toContinue);
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    toContinue |= (guid.Equals("00000000-0000-0000-0000-000000000000") || guid.Equals("") ||
                                   guid.Equals("00299570-246d-11d0-a768-00aa006e0529") || toContinue);

                    //DCSync rights
                    toContinue |= (guid.Equals("1131f6aa-9c07-11d1-f79f-00c04fc2dcd2") ||
                                   guid.Equals("1131f6ad-9c07-11d1-f79f-00c04fc2dcd2") || toContinue);
                }

                if (adRightString.Contains("WriteProperty"))
                {
                    toContinue |= (guid.Equals("00000000-0000-0000-0000-000000000000") ||
                                   guid.Equals("bf9679c0-0de6-11d0-a285-00aa003049e2") ||
                                   guid.Equals("bf9679a8-0de6-11d0-a285-00aa003049e2") ||
                                   guid.Equals("f30e3bc1-9ff0-11d1-b603-0000f80367c1") || toContinue);
                }

                var inheritedObjectType = ace != null?ace.InheritedObjectAceType.ToString() : "00000000-0000-0000-0000-000000000000";

                var isInherited = false;

                //Check if the ACE applies to us. This can either be because the ACE applies to any object type (the null guid)
                //or because the ACE replies to our object type (which is different per entry type).
                switch (entryType)
                {
                case "user":
                    isInherited = inheritedObjectType.Equals("00000000-0000-0000-0000-000000000000") ||
                                  inheritedObjectType.Equals("bf967aba-0de6-11d0-a285-00aa003049e2");
                    break;

                case "group":
                    isInherited = inheritedObjectType.Equals("00000000-0000-0000-0000-000000000000") ||
                                  inheritedObjectType.Equals("bf967a9c-0de6-11d0-a285-00aa003049e2");
                    break;

                case "domain":
                    isInherited = inheritedObjectType.Equals("00000000-0000-0000-0000-000000000000") ||
                                  inheritedObjectType.Equals("19195a5a-6da0-11d0-afd3-00c04fd930c9");
                    break;

                case "gpo":
                    isInherited = inheritedObjectType.Equals("00000000-0000-0000-0000-000000000000") ||
                                  inheritedObjectType.Equals("f30e3bc2-9ff0-11d1-b603-0000f80367c1");
                    break;
                }

                //Special case used for example by Exchange: the ACE is inherited but also applies to the object it is set on
                // this is verified by looking if this ACE is not inherited, and is not an inherit-only ACE
                if (!isInherited && !((ace.AceFlags & AceFlags.InheritOnly) == AceFlags.InheritOnly) && !((ace.AceFlags & AceFlags.Inherited) == AceFlags.Inherited))
                {
                    //If these conditions hold the ACE applies to this object anyway
                    isInherited = true;
                }

                if (!toContinue || !isInherited)
                {
                    continue;
                }

                string aceType = null;
                if (adRightString.Contains("ExtendedRight"))
                {
                    switch (guid)
                    {
                    case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2":
                        aceType = "DS-Replication-Get-Changes";
                        break;

                    case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2":
                        aceType = "DS-Replication-Get-Changes-All";
                        break;

                    //Though it doesn't make sense privilege wise, the Exchange reset password permissions also apply to the
                    //domain object. We need to catch this properly otherwise "All" access is assumed, which is incorrect
                    case "00299570-246d-11d0-a768-00aa006e0529":
                        aceType = "User-Force-Change-Password";
                        break;

                    default:
                        aceType = "All";
                        break;
                    }
                }

                //If we have either of the DCSync rights, store it in a temporary object and continue.
                //We need both rights for either right to mean anything to us
                if (aceType != null && entryType.Equals("domain") && (aceType.Equals("DS-Replication-Get-Changes-All") ||
                                                                      aceType.Equals("DS-Replication-Get-Changes")))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    if (aceType.Contains("-All"))
                    {
                        sync.GetChangesAll = true;
                    }
                    else
                    {
                        sync.GetChanges = true;
                    }

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                    continue;
                }

                if (aceType != null && entryType.Equals("domain") && aceType.Equals("All"))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    sync.GetChangesAll = true;
                    sync.GetChanges    = true;

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                }

                if (aceType != null && entryType.Equals("domain") && adRightString.Contains("GenericAll"))
                {
                    if (!_syncers.TryGetValue(mappedPrincipal.PrincipalName, out var sync))
                    {
                        sync = new DcSync
                        {
                            Domain        = entryDisplayName,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType
                        };
                    }

                    sync.GetChangesAll = true;
                    sync.GetChanges    = true;

                    _syncers.AddOrUpdate(mappedPrincipal.PrincipalName, sync, (key, oldVar) => sync);
                }

                //Return ACL objects based on rights + guid combos

                if (adRightString.Contains("GenericAll"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "GenericAll",
                        Qualifier = qAce.AceQualifier.ToString(),
                        ObjectGuid = entryGuid
                    });
                }

                if (adRightString.Contains("GenericWrite") && !entryType.Equals("domain"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "GenericWrite",
                        Qualifier = qAce.AceQualifier.ToString(),
                        ObjectGuid = entryGuid
                    });
                }

                if (adRightString.Contains("WriteOwner"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "WriteOwner",
                        Qualifier = qAce.AceQualifier.ToString(),
                        ObjectGuid = entryGuid
                    });
                }

                if (adRightString.Contains("WriteDacl"))
                {
                    yield return(new ACL
                    {
                        AceType = "",
                        Inherited = qAce.IsInherited,
                        PrincipalName = mappedPrincipal.PrincipalName,
                        PrincipalType = mappedPrincipal.ObjectType,
                        ObjectType = entryType,
                        ObjectName = entryDisplayName,
                        RightName = "WriteDacl",
                        Qualifier = qAce.AceQualifier.ToString(),
                        ObjectGuid = entryGuid
                    });
                }

                if (adRightString.Contains("WriteProperty"))
                {
                    if (guid.Equals("bf9679c0-0de6-11d0-a285-00aa003049e2") && !entryType.Equals("domain") && !entryType.Equals("gpo"))
                    {
                        yield return(new ACL
                        {
                            AceType = "Member",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "WriteProperty",
                            Qualifier = qAce.AceQualifier.ToString(),
                            ObjectGuid = entryGuid
                        });
                    }
                    //else if (guid.Equals("f30e3bc1-9ff0-11d1-b603-0000f80367c1") && entryType.Equals("gpo"))
                    //{
                    //    yield return new ACL
                    //    {
                    //        AceType = "GPC-File-Sys-Path",
                    //        Inherited = qAce.IsInherited,
                    //        PrincipalName = mappedPrincipal.PrincipalName,
                    //        PrincipalType = mappedPrincipal.ObjectType,
                    //        ObjectType = entryType,
                    //        ObjectName = entryDisplayName,
                    //        RightName = "WriteProperty",
                    //        Qualifier = qAce.AceQualifier.ToString(),
                    //        ObjectGuid = entryGuid
                    //    };
                    //}
                }

                if (adRightString.Contains("ExtendedRight"))
                {
                    if (guid.Equals("00299570-246d-11d0-a768-00aa006e0529") && !entryType.Equals("domain") && !entryType.Equals("gpo"))
                    {
                        yield return(new ACL
                        {
                            AceType = "User-Force-Change-Password",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "ExtendedRight",
                            Qualifier = qAce.AceQualifier.ToString(),
                            ObjectGuid = entryGuid
                        });
                    }
                    else if (guid.Equals("00000000-0000-0000-0000-000000000000"))
                    {
                        yield return(new ACL
                        {
                            AceType = "All",
                            Inherited = qAce.IsInherited,
                            PrincipalName = mappedPrincipal.PrincipalName,
                            PrincipalType = mappedPrincipal.ObjectType,
                            ObjectType = entryType,
                            ObjectName = entryDisplayName,
                            RightName = "ExtendedRight",
                            Qualifier = qAce.AceQualifier.ToString(),
                            ObjectGuid = entryGuid
                        });
                    }
                }
            }
        }