Example #1
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 #2
0
        /// <summary>
        /// Wraps the GetNetLocalGroupMembers call with a timeout, and then processes the results into objects
        /// </summary>
        /// <param name="computer"></param>
        /// <param name="rid">The relative ID of the group we want to query</param>
        /// <returns></returns>
        private static async Task <List <GenericMember> > GetNetLocalGroupMembers(Computer computer, LocalGroupRids rid)
        {
            var sids            = new IntPtr[0];
            var groupMemberList = new List <GenericMember>();
            var task            = Task.Run(() => CallLocalGroupApi(computer, rid, out sids));

            //Run the API call along with a 10 second timeout
            if (await Task.WhenAny(task, Task.Delay(10000)) != task)
            {
                OutputTasks.AddComputerStatus(new ComputerStatus
                {
                    ComputerName = computer.DisplayName,
                    Status       = "Timeout",
                    Task         = $"GetNetLocalGroup-{rid}"
                });
                return(groupMemberList);
            }

            //Check the result of the task
            var taskResult = task.Result;

            if (!taskResult)
            {
                return(groupMemberList);
            }

            if (Options.Instance.DumpComputerStatus)
            {
                OutputTasks.AddComputerStatus(new ComputerStatus
                {
                    ComputerName = computer.DisplayName,
                    Status       = "Success",
                    Task         = $"GetNetLocalGroup-{rid}"
                });
            }

            //Take our pointers to sids and convert them into string sids for matching
            var convertedSids = new List <string>();

            for (var i = 0; i < sids.Length; i++)
            {
                try
                {
                    var sid = new SecurityIdentifier(sids[i]).Value;
                    convertedSids.Add(sid);
                }
                catch
                {
                    //SID Resolution failed for some reason, so ignore it
                }
                finally
                {
                    //Set the IntPtr to zero, so we can GC those
                    sids[i] = IntPtr.Zero;
                }
            }
            //Null out sids, so garbage collection takes care of it
            sids = null;

            //Extract the domain SID from the computer's sid, to avoid creating more SecurityIdentifier objects
            var domainSid = computer.ObjectIdentifier.Substring(0, computer.ObjectIdentifier.LastIndexOf('-'));

            // The first account in our list should always be the default RID 500 for the machine, but we'll take some extra precautions
            var machineSid = convertedSids.DefaultIfEmpty("DUMMYSTRING").FirstOrDefault(x => x.EndsWith("-500") && !x.StartsWith(domainSid)) ?? "DUMMYSTRING";

            //If we found a machine sid, strip the ending bit off
            if (machineSid.StartsWith("S-1-5-21"))
            {
                machineSid = machineSid.Substring(0, machineSid.LastIndexOf('-'));
            }

            foreach (var sid in convertedSids)
            {
                //Filter out local accounts
                if (sid.StartsWith(machineSid))
                {
                    continue;
                }

                var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(sid, computer.Domain);

                //Filter out null sids, usually from deconflictions
                if (finalSid == null)
                {
                    continue;
                }

                groupMemberList.Add(new GenericMember
                {
                    MemberType = type,
                    MemberId   = finalSid
                });
            }

            return(groupMemberList);
        }
Example #3
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);
        }