internal static async Task <LdapWrapper> ResolveObjectProperties(LdapWrapper wrapper)
        {
            var result = wrapper.SearchResult;

            wrapper.Properties.Add("description", result.GetProperty("description"));

            if (wrapper is Domain domain)
            {
                ParseDomainProperties(domain);
            }
            else if (wrapper is Computer computer)
            {
                await ParseComputerProperties(computer);
            }
            else if (wrapper is User user)
            {
                await ParseUserProperties(user);
            }
            else if (wrapper is GPO gpo)
            {
                ParseGPOProperties(gpo);
            }
            else if (wrapper is OU ou)
            {
                ParseOUProperties(ou);
            }
            else if (wrapper is Group group)
            {
                ParseGroupProperties(group);
            }

            return(wrapper);
        }
Example #2
0
        internal static void WriteJsonOutput(LdapWrapper wrapper)
        {
            switch (wrapper)
            {
            case Computer computer:
                _computerOutput.Value.WriteObject(computer);
                break;

            case Domain domain:
                _domainOutput.Value.WriteObject(domain);
                break;

            case GPO gpo:
                _gpoOutput.Value.WriteObject(gpo);
                break;

            case Group group:
                _groupOutput.Value.WriteObject(group);
                break;

            case OU ou:
                _ouOutput.Value.WriteObject(ou);
                break;

            case User user:
                _userOutput.Value.WriteObject(user);
                break;
            }

            _currentCount++;
        }
Example #3
0
        internal static async Task <LdapWrapper> ProcessNetSessions(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer && !computer.PingFailed)
            {
                //If ExcludeDC is set remove DCs from collection
                if (Options.Instance.ExcludeDomainControllers && computer.IsDomainController)
                {
                    return(wrapper);
                }

                //If stealth is set, only do session enum if the computer is marked as a stealth target
                if (Options.Instance.Stealth && !computer.IsStealthTarget)
                {
                    return(wrapper);
                }

                var sessions = await GetNetSessions(computer);

                var temp = computer.Sessions.ToList();
                temp.AddRange(sessions);
                computer.Sessions = temp.Distinct().ToArray();
                await Helpers.DoDelay();
            }

            return(wrapper);
        }
Example #4
0
        /// <summary>
        /// Gets the primary group info for users/computers
        /// </summary>
        /// <param name="wrapper"></param>
        private static void GetPrimaryGroupInfo(LdapWrapper wrapper)
        {
            //Grab the primarygroupid attribute
            var primaryGroupId = wrapper.SearchResult.GetProperty("primarygroupid");

            if (primaryGroupId == null)
            {
                return;
            }

            //Grab the domain sid from the wrapper instead of querying LDAP
            var domainSid = wrapper.ObjectIdentifier.Substring(0, wrapper.ObjectIdentifier.LastIndexOf("-", StringComparison.Ordinal));

            //Append the primarygroupid to the domainsid
            var primaryGroupSid = $"{domainSid}-{primaryGroupId}";

            if (wrapper is Computer c)
            {
                c.PrimaryGroupSid = primaryGroupSid;
            }
            else if (wrapper is User u)
            {
                u.PrimaryGroupSid = primaryGroupSid;
            }
        }
        internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper)
        {
            //Only perform checks if this is a Computer object
            if (wrapper is Computer computer)
            {
                //Stealth targetting - we've already determined our stealth targets, so if its not a stealth target, return
                if (Options.Instance.Stealth && !computer.IsStealthTarget)
                {
                    return(wrapper);
                }

                if (Options.Instance.WindowsOnly)
                {
                    //If the WindowsOnly flag is set, check the operatingsystem attribute
                    var os = wrapper.SearchResult.GetProperty("operatingsystem");

                    //Perform a search for the term windows in the operatingsystem string
                    if (!(os?.IndexOf("windows", StringComparison.CurrentCultureIgnoreCase) > -1))
                    {
                        //If this isn't a windows computer, we'll mark is as such and we'll skip the following port scan since its not necessary
                        computer.IsWindows = false;

                        //Add a computer status message to note why we skipped this computer
                        OutputTasks.AddComputerStatus(new ComputerStatus
                        {
                            ComputerName = computer.DisplayName,
                            Status       = "NotWindows",
                            Task         = "SMBCheck"
                        });
                        return(wrapper);
                    }
                }

                //If we're skipping port scan, just return the wrapper. PingFailed is set to false by default
                if (Options.Instance.SkipPortScan)
                {
                    return(wrapper);
                }

                //Do a check on port 445 and save the result
                computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false;
                if (computer.PingFailed && Options.Instance.DumpComputerStatus)
                {
                    //If the port check failed, add a computer status note
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "SMBNotAvailable",
                        Task         = "SMBCheck"
                    });
                }

                //Do jitter/delay if specified
                await Helpers.DoDelay();
            }

            return(wrapper);
        }
Example #6
0
        internal static LdapWrapper ResolveDomainTrusts(LdapWrapper wrapper)
        {
            if (wrapper is Domain domain)
            {
                DoTrustEnumeration(domain);
            }

            return(wrapper);
        }
Example #7
0
 internal void WriteObject(LdapWrapper json)
 {
     Serializer.Serialize(JsonWriter, json);
     Count++;
     if (Count % 100 == 0)
     {
         JsonWriter.Flush();
     }
 }
Example #8
0
        internal static async Task <LdapWrapper> ProcessSPNS(LdapWrapper wrapper)
        {
            if (wrapper is User user)
            {
                await ProcessUserSPNs(user);
            }

            return(wrapper);
        }
Example #9
0
        /// <summary>
        /// Parses remaining properties when the --CollectAllProperties flag is specified
        /// </summary>
        /// <param name="wrapper"></param>
        private static void ParseAllProperties(LdapWrapper wrapper)
        {
            var result = wrapper.SearchResult;
            var flag   = IsTextUnicodeFlags.IS_TEXT_UNICODE_STATISTICS;

            foreach (var property in result.Attributes.AttributeNames)
            {
                var propName = property.ToString().ToLower();
                if (ReservedAttributes.Contains(propName))
                {
                    continue;
                }

                var collection = result.Attributes[propName];
                if (collection.Count == 0)
                {
                    continue;
                }
                if (collection.Count == 1)
                {
                    var testBytes = result.GetPropertyAsBytes(propName);

                    if (testBytes == null || testBytes.Length == 0 || !IsTextUnicode(testBytes, testBytes.Length, ref flag))
                    {
                        continue;
                    }

                    var testString = result.GetProperty(propName);

                    if (!string.IsNullOrEmpty(testString))
                    {
                        if (propName == "badpasswordtime")
                        {
                            wrapper.Properties.Add(propName, ConvertToUnixEpoch(testString));
                        }
                        else
                        {
                            wrapper.Properties.Add(propName, BestGuessConvert(testString));
                        }
                    }
                }
                else
                {
                    var arrBytes = result.GetPropertyAsArrayOfBytes(propName);
                    if (arrBytes.Length == 0 || !IsTextUnicode(arrBytes[0], arrBytes[0].Length, ref flag))
                    {
                        continue;
                    }

                    var arr = result.GetPropertyAsArray(propName);
                    if (arr.Length > 0)
                    {
                        wrapper.Properties.Add(propName, arr.Select(BestGuessConvert).ToArray());
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// Base function for processing ACES
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns></returns>
        internal static async Task <LdapWrapper> ProcessAces(LdapWrapper wrapper)
        {
            var aclAces = await ProcessDACL(wrapper);

            var gmsaAces = await ProcessGMSA(wrapper);

            wrapper.Aces = aclAces.Concat(gmsaAces).ToArray();
            return(wrapper);
        }
Example #11
0
        /// <summary>
        /// Processes the msds-groupmsamembership property, and determines who can read the password
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns></returns>
        private static async Task <List <ACL> > ProcessGMSA(LdapWrapper wrapper)
        {
            var aces = new List <ACL>();
            //Grab the property as a byte array
            var securityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("msds-groupmsamembership");

            //If the property is null, its either not a GMSA or something went wrong, so just exit out
            if (securityDescriptor == null)
            {
                return(aces);
            }

            //Create a new ActiveDirectorySecurity object and set the bytes to the descriptor
            var descriptor = new ActiveDirectorySecurity();

            descriptor.SetSecurityDescriptorBinaryForm(securityDescriptor);

            // Loop over the entries in the security descriptor
            foreach (ActiveDirectoryAccessRule ace in descriptor.GetAccessRules(true, true, typeof(SecurityIdentifier)))
            {
                //Ignore null aces
                if (ace == null)
                {
                    continue;
                }

                //Ignore deny aces (although this should never show up in GMSAs
                if (ace.AccessControlType == AccessControlType.Deny)
                {
                    continue;
                }

                //Pre-process the principal for the SID
                var principalSid = FilterAceSids(ace.IdentityReference.Value);

                //Ignore null SIDs
                if (principalSid == null)
                {
                    continue;
                }

                //Resolve the principal SID and grab its type
                var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(principalSid, wrapper.Domain);

                aces.Add(new ACL
                {
                    RightName     = "ReadGMSAPassword",
                    AceType       = "",
                    PrincipalSID  = finalSid,
                    PrincipalType = type,
                    IsInherited   = false
                });
            }

            return(aces);
        }
Example #12
0
        internal static async Task <LdapWrapper> EnumerateContainer(LdapWrapper wrapper)
        {
            if (wrapper is OU ou)
            {
                await ProcessOUObject(ou);
            }
            else if (wrapper is Domain domain)
            {
                await ProcessDomainObject(domain);
            }

            return(wrapper);
        }
Example #13
0
        internal static async Task <LdapWrapper> ProcessGroupMembership(LdapWrapper wrapper)
        {
            if (wrapper is Group group)
            {
                await GetGroupMembership(group);
            }
            else if (wrapper is Computer || wrapper is User)
            {
                GetPrimaryGroupInfo(wrapper);
            }

            return(wrapper);
        }
Example #14
0
        /// <summary>
        /// Grab properties from Group objects
        /// </summary>
        /// <param name="wrapper"></param>
        private static void ParseGroupProperties(LdapWrapper wrapper)
        {
            var result = wrapper.SearchResult;

            var adminCount = result.GetProperty("admincount");

            if (adminCount != null)
            {
                var a = int.Parse(adminCount);
                wrapper.Properties.Add("admincount", a != 0);
            }
            else
            {
                wrapper.Properties.Add("admincount", false);
            }
        }
Example #15
0
        internal static async Task <LdapWrapper> ProcessLoggedOn(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer && !computer.PingFailed)
            {
                var sessions = new List <Session>();
                sessions.AddRange(await GetLoggedOnUsersAPI(computer));
                sessions.AddRange(GetLoggedOnUsersRegistry(computer));
                var temp = computer.Sessions.ToList();
                temp.AddRange(sessions);
                computer.Sessions = temp.Distinct().ToArray();
            }

            await Helpers.DoDelay();

            return(wrapper);
        }
        /// <summary>
        /// Post-processing on wrapper objects to set stealth/domain controller targets
        /// </summary>
        /// <param name="wrapper"></param>
        private static void PostProcessWrapper(LdapWrapper wrapper)
        {
            var opts = Options.Instance;

            if (wrapper is Computer computer)
            {
                if (opts.Stealth && StealthProducer.IsSidStealthTarget(computer.ObjectIdentifier))
                {
                    computer.IsStealthTarget = true;
                }

                if (opts.ExcludeDomainControllers && BaseProducer.IsSidDomainController(computer.ObjectIdentifier))
                {
                    computer.IsDomainController = true;
                }
            }
        }
        /// <summary>
        /// Entrypoint for the pipeline
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns></returns>
        internal static async Task <LdapWrapper> ProcessLoggedOn(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer)
            {
                //Make sure we're targetting a windows or non-contactable computer
                if (computer.IsWindows && !computer.PingFailed)
                {
                    var sessions = new List <Session>();
                    sessions.AddRange(await GetLoggedOnUsersAPI(computer));
                    sessions.AddRange(GetLoggedOnUsersRegistry(computer));
                    var temp = computer.Sessions.ToList();
                    temp.AddRange(sessions);
                    computer.Sessions = temp.Distinct().ToArray();
                }
            }

            await Helpers.DoDelay();

            return(wrapper);
        }
Example #18
0
        private static void GetPrimaryGroupInfo(LdapWrapper wrapper)
        {
            var primaryGroupId = wrapper.SearchResult.GetProperty("primarygroupid");

            if (primaryGroupId == null)
            {
                return;
            }
            var domainSid       = wrapper.ObjectIdentifier.Substring(0, wrapper.ObjectIdentifier.LastIndexOf("-", StringComparison.Ordinal));
            var primaryGroupSid = $"{domainSid}-{primaryGroupId}";

            if (wrapper is Computer c)
            {
                c.PrimaryGroupSid = primaryGroupSid;
            }
            else if (wrapper is User u)
            {
                u.PrimaryGroupSid = primaryGroupSid;
            }
        }
Example #19
0
        internal static async Task <LdapWrapper> GetLocalGroupMembers(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer && computer.IsWindows && !computer.PingFailed)
            {
                var opts = Options.Instance.ResolvedCollectionMethods;
                if ((opts & CollectionMethodResolved.DCOM) != 0)
                {
                    var temp = computer.DcomUsers.ToList();
                    temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.DcomUsers)).Distinct());
                    computer.DcomUsers = temp.ToArray();
                    await Helpers.DoDelay();
                }

                if ((opts & CollectionMethodResolved.LocalAdmin) != 0)
                {
                    var temp = computer.LocalAdmins.ToList();
                    temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.Administrators)).Distinct());
                    computer.LocalAdmins = temp.ToArray();
                    await Helpers.DoDelay();
                }

                if ((opts & CollectionMethodResolved.RDP) != 0)
                {
                    var temp = computer.RemoteDesktopUsers.ToList();
                    temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.RemoteDesktopUsers)).Distinct());
                    computer.RemoteDesktopUsers = temp.ToArray();
                    await Helpers.DoDelay();
                }


                if ((opts & CollectionMethodResolved.PSRemote) != 0)
                {
                    var temp = computer.PSRemoteUsers.ToList();
                    temp.AddRange((await GetNetLocalGroupMembers(computer, LocalGroupRids.PSRemote)).Distinct());
                    computer.PSRemoteUsers = temp.ToArray();
                    await Helpers.DoDelay();
                }
            }

            return(wrapper);
        }
        internal static async Task <LdapWrapper> CheckSMBOpen(LdapWrapper wrapper)
        {
            if (wrapper is Computer computer)
            {
                if (Options.Instance.Stealth && !computer.IsStealthTarget)
                {
                    return(wrapper);
                }
                computer.PingFailed = Helpers.CheckPort(computer.APIName, 445) == false;
                if (computer.PingFailed && Options.Instance.DumpComputerStatus)
                {
                    OutputTasks.AddComputerStatus(new ComputerStatus
                    {
                        ComputerName = computer.DisplayName,
                        Status       = "SMBNotAvailable",
                        Task         = "SMBCheck"
                    });
                }

                await Helpers.DoDelay();
            }

            return(wrapper);
        }
Example #21
0
 internal static LdapWrapper ProcessDACL(LdapWrapper wrapper)
 {
 }
Example #22
0
        internal static async Task <LdapWrapper> ProcessDACL(LdapWrapper wrapper)
        {
            var aces = new List <ACL>();
            var ntSecurityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("ntsecuritydescriptor");

            //If the NTSecurityDescriptor is null, something screwy is happening. Nothing to process here, so continue in the pipeline
            if (ntSecurityDescriptor == null)
            {
                return(wrapper);
            }

            var descriptor = new ActiveDirectorySecurity();

            descriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);

            var ownerSid = ProcessACESID(descriptor.GetOwner(typeof(SecurityIdentifier)).Value);

            if (ownerSid != null)
            {
                if (CommonPrincipal.GetCommonSid(ownerSid, out var commonPrincipal))
                {
                    aces.Add(new ACL
                    {
                        PrincipalSID  = Helpers.ConvertCommonSid(ownerSid, wrapper.Domain),
                        RightName     = "Owner",
                        AceType       = "",
                        PrincipalType = commonPrincipal.Type,
                        IsInherited   = false
                    });
                }
                else
                {
                    var ownerType = await Helpers.LookupSidType(ownerSid);

                    aces.Add(new ACL
                    {
                        PrincipalSID  = ownerSid,
                        RightName     = "Owner",
                        AceType       = "",
                        PrincipalType = ownerType,
                        IsInherited   = false
                    });
                }
            }

            foreach (ActiveDirectoryAccessRule ace in descriptor.GetAccessRules(true,
                                                                                true, typeof(SecurityIdentifier)))
            {
                //Ignore Null Aces
                if (ace == null)
                {
                    continue;
                }
                //Ignore deny aces
                if (ace.AccessControlType == AccessControlType.Deny)
                {
                    continue;
                }

                //Check if the ACE actually applies to our object based on the object type
                if (!IsAceInherited(ace, BaseGuids[wrapper.GetType()]))
                {
                    continue;
                }

                var principalSid = ProcessACESID(ace.IdentityReference.Value);

                if (principalSid == null)
                {
                    continue;
                }

                LdapTypeEnum principalType;
                if (CommonPrincipal.GetCommonSid(principalSid, out var commonPrincipal))
                {
                    principalSid  = Helpers.ConvertCommonSid(principalSid, wrapper.Domain);
                    principalType = commonPrincipal.Type;
                }
                else
                {
                    principalType = await Helpers.LookupSidType(principalSid);
                }

                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();
                var isInherited   = ace.IsInherited;

                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            PrincipalSID  = principalSid,
                            RightName     = "GenericAll",
                            AceType       = "",
                            PrincipalType = principalType,
                            IsInherited   = isInherited
                        });
                    }
                    //GenericAll includes every other right, and we dont want to duplicate. So continue in the loop
                    continue;
                }

                //WriteDacl and WriteOwner are always useful to us regardless of object type
                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        PrincipalSID  = principalSid,
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalType = principalType,
                        IsInherited   = isInherited
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        RightName     = "WriteOwner",
                        AceType       = "",
                        PrincipalSID  = principalSid,
                        PrincipalType = principalType,
                        IsInherited   = isInherited
                    });
                }

                //Process object specific ACEs
                //Extended rights apply to Users, Domains, Computers
                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (wrapper is Domain)
                    {
                        switch (objectAceType)
                        {
                        case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2":
                            aces.Add(new ACL
                            {
                                AceType       = "GetChanges",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                            break;

                        case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2":
                            aces.Add(new ACL
                            {
                                AceType       = "GetChangesAll",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                            break;

                        case AllGuid:
                        case "":
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                            break;
                        }
                    }
                    else if (wrapper is User)
                    {
                        switch (objectAceType)
                        {
                        case "00299570-246d-11d0-a768-00aa006e0529":
                            aces.Add(new ACL
                            {
                                AceType       = "User-Force-Change-Password",
                                PrincipalSID  = principalSid,
                                RightName     = "ExtendedRight",
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                            break;

                        case AllGuid:
                        case "":
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                PrincipalSID  = principalSid,
                                RightName     = "ExtendedRight",
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                            break;
                        }
                    }
                    else if (wrapper is Computer)
                    {
                        Helpers.GetDirectorySearcher(wrapper.Domain).GetNameFromGuid(objectAceType, out var mappedGuid);
                        if (wrapper.SearchResult.GetProperty("ms-mcs-admpwdexpirationtime") != null)
                        {
                            if (objectAceType == AllGuid || objectAceType == "")
                            {
                                aces.Add(new ACL
                                {
                                    AceType       = "All",
                                    RightName     = "ExtendedRight",
                                    PrincipalSID  = principalSid,
                                    PrincipalType = principalType,
                                    IsInherited   = isInherited
                                });
                            }
                            else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                            {
                                aces.Add(new ACL
                                {
                                    AceType       = "",
                                    RightName     = "ReadLAPSPassword",
                                    PrincipalSID  = principalSid,
                                    PrincipalType = principalType,
                                    IsInherited   = isInherited
                                });
                            }
                        }
                    }
                }

                //PropertyWrites apply to Groups, User, Computer
                //GenericWrite encapsulates WriteProperty, so we need to check them at the same time to avoid duplicate edges
                if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) ||
                    rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            AceType       = "",
                            RightName     = "GenericWrite",
                            PrincipalSID  = principalSid,
                            PrincipalType = principalType,
                            IsInherited   = isInherited
                        });
                    }

                    if (wrapper is User)
                    {
                        if (objectAceType == "f3a64788-5306-11d1-a9c5-0000f80367c1")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "WriteSPN",
                                RightName     = "WriteProperty",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                        }
                    }
                    else if (wrapper is Group)
                    {
                        if (objectAceType == "bf9679c0-0de6-11d0-a285-00aa003049e2")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AddMember",
                                RightName     = "WriteProperty",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                        }
                    }
                    else if (wrapper is Computer)
                    {
                        if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AllowedToAct",
                                RightName     = "WriteProperty",
                                PrincipalSID  = principalSid,
                                PrincipalType = principalType,
                                IsInherited   = isInherited
                            });
                        }
                    }
                }
            }

            wrapper.Aces = aces.Distinct().ToArray();
            return(wrapper);
        }
Example #23
0
        /// <summary>
        /// Processes the ACL for an object
        /// </summary>
        /// <param name="wrapper"></param>
        /// <returns></returns>
        private static async Task <List <ACL> > ProcessDACL(LdapWrapper wrapper)
        {
            var aces = new List <ACL>();
            //Grab the ntsecuritydescriptor attribute as bytes
            var ntSecurityDescriptor = wrapper.SearchResult.GetPropertyAsBytes("ntsecuritydescriptor");

            //If the NTSecurityDescriptor is null, something screwy is happening. Nothing to process here, so continue in the pipeline
            if (ntSecurityDescriptor == null)
            {
                return(aces);
            }

            //Create a new ActiveDirectorySecurity object and set the bytes in to this value
            var descriptor = new ActiveDirectorySecurity();

            descriptor.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);

            //Pre-process the sid of the object owner
            var ownerSid = FilterAceSids(descriptor.GetOwner(typeof(SecurityIdentifier)).Value);

            if (ownerSid != null)
            {
                //Resolve the owner's SID to its corresponding type
                var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(ownerSid, wrapper.Domain);

                //If resolution worked, store the Owner ACE into our final result
                if (finalSid != null)
                {
                    aces.Add(new ACL
                    {
                        PrincipalSID  = finalSid,
                        RightName     = "Owner",
                        AceType       = "",
                        PrincipalType = type,
                        IsInherited   = false
                    });
                }
            }

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

                //Ignore deny aces
                if (ace.AccessControlType == AccessControlType.Deny)
                {
                    continue;
                }

                //Check if the ACE actually applies to our object based on the object type
                if (!IsAceInherited(ace, BaseGuids[wrapper.GetType()]))
                {
                    continue;
                }

                //Grab the sid of the principal on this ACE
                var principalSid = FilterAceSids(ace.IdentityReference.Value);

                if (principalSid == null)
                {
                    continue;
                }

                //Resolve the principal's SID to its type
                var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(principalSid, wrapper.Domain);

                if (finalSid == null)
                {
                    continue;
                }

                //Start processing the rights in this ACE
                var rights        = ace.ActiveDirectoryRights;
                var objectAceType = ace.ObjectType.ToString();
                var isInherited   = ace.IsInherited;

                //GenericAll is applicable to everything
                if (rights.HasFlag(ActiveDirectoryRights.GenericAll))
                {
                    if (objectAceType == AllGuid || objectAceType == "")
                    {
                        aces.Add(new ACL
                        {
                            PrincipalSID  = finalSid,
                            RightName     = "GenericAll",
                            AceType       = "",
                            PrincipalType = type,
                            IsInherited   = isInherited
                        });
                    }
                    //GenericAll includes every other right, and we dont want to duplicate. So continue in the loop
                    continue;
                }

                //WriteDacl and WriteOwner are always useful to us regardless of object type
                if (rights.HasFlag(ActiveDirectoryRights.WriteDacl))
                {
                    aces.Add(new ACL
                    {
                        PrincipalSID  = finalSid,
                        AceType       = "",
                        RightName     = "WriteDacl",
                        PrincipalType = type,
                        IsInherited   = isInherited
                    });
                }

                if (rights.HasFlag(ActiveDirectoryRights.WriteOwner))
                {
                    aces.Add(new ACL
                    {
                        RightName     = "WriteOwner",
                        AceType       = "",
                        PrincipalSID  = finalSid,
                        PrincipalType = type,
                        IsInherited   = isInherited
                    });
                }

                //Process object specific ACEs
                //Extended rights apply to Users, Domains, Computers
                if (rights.HasFlag(ActiveDirectoryRights.ExtendedRight))
                {
                    if (wrapper is Domain)
                    {
                        switch (objectAceType)
                        {
                        case "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2":
                            aces.Add(new ACL
                            {
                                AceType       = "GetChanges",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                            break;

                        case "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2":
                            aces.Add(new ACL
                            {
                                AceType       = "GetChangesAll",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                            break;

                        case AllGuid:
                        case "":
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                RightName     = "ExtendedRight",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                            break;
                        }
                    }
                    else if (wrapper is User)
                    {
                        switch (objectAceType)
                        {
                        case "00299570-246d-11d0-a768-00aa006e0529":
                            aces.Add(new ACL
                            {
                                AceType       = "User-Force-Change-Password",
                                PrincipalSID  = finalSid,
                                RightName     = "ExtendedRight",
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                            break;

                        case AllGuid:
                        case "":
                            aces.Add(new ACL
                            {
                                AceType       = "All",
                                PrincipalSID  = finalSid,
                                RightName     = "ExtendedRight",
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                            break;
                        }
                    }
                    else if (wrapper is Computer)
                    {
                        //Computer extended rights are important when the computer has LAPS
                        Helpers.GetDirectorySearcher(wrapper.Domain).GetAttributeFromGuid(objectAceType, out var mappedGuid);
                        if (wrapper.SearchResult.GetProperty("ms-mcs-admpwdexpirationtime") != null)
                        {
                            if (objectAceType == AllGuid || objectAceType == "")
                            {
                                aces.Add(new ACL
                                {
                                    AceType       = "All",
                                    RightName     = "ExtendedRight",
                                    PrincipalSID  = finalSid,
                                    PrincipalType = type,
                                    IsInherited   = isInherited
                                });
                            }
                            else if (mappedGuid != null && mappedGuid == "ms-Mcs-AdmPwd")
                            {
                                aces.Add(new ACL
                                {
                                    AceType       = "",
                                    RightName     = "ReadLAPSPassword",
                                    PrincipalSID  = finalSid,
                                    PrincipalType = type,
                                    IsInherited   = isInherited
                                });
                            }
                        }
                    }
                }

                //PropertyWrites apply to Groups, User, Computer, GPO
                //GenericWrite encapsulates WriteProperty, so we need to check them at the same time to avoid duplicate edges
                if (rights.HasFlag(ActiveDirectoryRights.GenericWrite) ||
                    rights.HasFlag(ActiveDirectoryRights.WriteProperty))
                {
                    if (wrapper is User || wrapper is Group || wrapper is Computer || wrapper is GPO)
                    {
                        if (objectAceType == AllGuid || objectAceType == "")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "",
                                RightName     = "GenericWrite",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                        }
                    }

                    if (wrapper is User)
                    {
                        if (objectAceType == "f3a64788-5306-11d1-a9c5-0000f80367c1")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "WriteSPN",
                                RightName     = "WriteProperty",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                        }
                    }
                    else if (wrapper is Group)
                    {
                        if (objectAceType == "bf9679c0-0de6-11d0-a285-00aa003049e2")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AddMember",
                                RightName     = "WriteProperty",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                        }
                    }
                    else if (wrapper is Computer)
                    {
                        if (objectAceType == "3f78c3e5-f79a-46bd-a0b8-9d18116ddc79")
                        {
                            aces.Add(new ACL
                            {
                                AceType       = "AllowedToAct",
                                RightName     = "WriteProperty",
                                PrincipalSID  = finalSid,
                                PrincipalType = type,
                                IsInherited   = isInherited
                            });
                        }
                    }
                }
            }

            return(aces);
        }