Exemple #1
0
        private static MappedPrincipal GetAclOwner(ActiveDirectorySecurity acl, string domainName)
        {
            var sid = acl.GetOwner(typeof(SecurityIdentifier)).Value;

            //Filter Local System/Creator Owner/Principal Self
            if (sid == "S-1-5-18" || sid == "S-1-3-0" || sid == "S-1-5-10")
            {
                return(null);
            }

            if (!_nullSids.TryGetValue(sid, out _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(sid, out var owner))
                {
                    //Resolve the sid manually if we still dont have it
                    var ownerDomain = _utils.SidToDomainName(sid) ?? domainName;
                    owner = _utils.UnknownSidTypeToDisplay(sid, ownerDomain, Props);
                }
                else
                {
                    owner.PrincipalName = $"{owner.PrincipalName}@{domainName}";
                }

                //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                if (owner == null)
                {
                    _nullSids.TryAdd(sid, new byte());
                }

                return(owner);
            }

            return(null);
        }
Exemple #2
0
        private static MappedPrincipal GetAcePrincipal(ActiveDirectoryAccessRule rule, string domainName)
        {
            var sid = rule.IdentityReference.Value;

            //Filter Local System/Creator Owner/Principal Self
            if (sid == "S-1-5-18" || sid == "S-1-3-0" || sid == "S-1-5-10")
            {
                return(null);
            }

            if (!_nullSids.TryGetValue(sid, out _))
            {
                //Check if its a common SID
                if (!MappedPrincipal.GetCommon(sid, out var principal))
                {
                    //Resolve the sid manually if we still don't have it
                    var ownerDomain = _utils.SidToDomainName(sid) ?? domainName;
                    principal = _utils.UnknownSidTypeToDisplay(sid, ownerDomain, Props);
                }
                else
                {
                    if (sid == "S-1-5-9")
                    {
                        var dObj = _utils.GetForest(domainName);
                        var d    = dObj == null ? domainName : dObj.RootDomain.Name;
                        principal.PrincipalName = $"ENTERPRISE DOMAIN CONTROLLERS@{d}".ToUpper();
                    }
                    else
                    {
                        principal.PrincipalName = $"{principal.PrincipalName}@{domainName}";
                    }
                }

                //We'll cache SIDs we've failed to resolve previously so we dont keep trying
                if (principal == null)
                {
                    _nullSids.TryAdd(sid, new byte());
                }

                return(principal);
            }

            return(null);
        }
Exemple #3
0
        public static IEnumerable <LocalMember> GetGroupMembers(ResolvedEntry entry, LocalGroupRids rid)
        {
            if (rid.Equals(LocalGroupRids.Administrators) && !Utils.IsMethodSet(ResolvedCollectionMethod.LocalAdmin))
            {
                yield break;
            }

            if (rid.Equals(LocalGroupRids.RemoteDesktopUsers) && !Utils.IsMethodSet(ResolvedCollectionMethod.RDP))
            {
                yield break;
            }

            if (rid.Equals(LocalGroupRids.DcomUsers) && !Utils.IsMethodSet(ResolvedCollectionMethod.DCOM))
            {
                yield break;
            }

            Utils.Debug("Starting GetSamAdmins");
            string machineSid = null;

            Utils.Debug("Starting Task");
            var t = Task <SamEnumerationObject[]> .Factory.StartNew(() =>
            {
                try
                {
                    return(NetLocalGroupGetMembers(entry, (int)rid, out machineSid));
                }
                catch (ApiFailedException)
                {
                    return(new SamEnumerationObject[0]);
                }
                catch (SystemDownException)
                {
                    return(new SamEnumerationObject[0]);
                }
            });

            var success = t.Wait(Timeout);

            Utils.Debug("Task Finished");

            if (!success)
            {
                Utils.Debug("SamAdmin Timeout");
                throw new TimeoutException();
            }

            Utils.Debug("SamAdmin success");
            var resolvedObjects = t.Result;

            if (resolvedObjects.Length == 0)
            {
                Utils.Debug("SamAdmins returned 0 objects");
                yield break;
            }

            Utils.Debug("Processing data");
            //Process our list of stuff now
            foreach (var data in resolvedObjects)
            {
                var sid = data?.AccountSid;
                Utils.Debug($"Processing sid: {sid}");
                if (sid == null)
                {
                    Utils.Debug("Null sid");
                    continue;
                }

                if (data.AccountName.Equals(string.Empty))
                {
                    Utils.Debug("Empty AccountName");
                    continue;
                }


                if (sid.StartsWith(machineSid))
                {
                    Utils.Debug("Local Account");
                    continue;
                }


                string type;
                switch (data.SidUsage)
                {
                case SidNameUse.SidTypeUser:
                    type = "user";
                    break;

                case SidNameUse.SidTypeGroup:
                    type = "group";
                    break;

                case SidNameUse.SidTypeComputer:
                    type = "computer";
                    break;

                case SidNameUse.SidTypeWellKnownGroup:
                    type = "wellknown";
                    break;

                case SidNameUse.SidTypeAlias:
                    type = "group";
                    break;

                default:
                    type = null;
                    break;
                }

                if (type == null)
                {
                    continue;
                }

                if (data.AccountName.EndsWith("$"))
                {
                    type = "unknown";
                }

                string resolvedName;

                Utils.Debug($"Object Type: {type}");

                if (type.Equals("unknown"))
                {
                    Utils.Debug("Resolving Sid to object UnknownType");
                    var mp = _utils.UnknownSidTypeToDisplay(sid, _utils.SidToDomainName(sid),
                                                            AdminProps);
                    if (mp == null)
                    {
                        continue;
                    }

                    Utils.Debug($"Got Object: {mp.PrincipalName}");
                    resolvedName = mp.PrincipalName;
                    type         = mp.ObjectType;
                }
                else if (type == "wellknown")
                {
                    if (MappedPrincipal.GetCommon(sid, out var result))
                    {
                        if (result.PrincipalName.Equals("Local System"))
                        {
                            continue;
                        }

                        string domain;
                        try
                        {
                            var split = string.Join(".", entry.IngestCacheDisplay.Split('.').Skip(1).ToArray());
                            domain = split;
                        }
                        catch
                        {
                            domain = _utils.GetDomain(_options.Domain).Name;
                        }

                        type         = result.ObjectType;
                        resolvedName = $"{result.PrincipalName}@{domain}".ToUpper();
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    Utils.Debug("Resolving Sid to Object");
                    resolvedName = _utils.SidToDisplay(sid, _utils.SidToDomainName(sid), AdminProps, type);
                    if (resolvedName == null)
                    {
                        continue;
                    }
                    Utils.Debug($"Got Object: {resolvedName}");
                }

                yield return(new LocalMember
                {
                    Type = type,
                    Name = resolvedName
                });
            }

            Utils.DoJitter();
        }
Exemple #4
0
        public static void GetObjectAces(SearchResultEntry entry, ResolvedEntry resolved, ref Ou g)
        {
            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;
                }

                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 dObj = _utils.GetForest(domainName);
                        var d    = dObj == null ? domainName : dObj.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 flags       = ace == null ? AceFlags.None : ace.AceFlags;
                var isInherited = (flags & AceFlags.InheritOnly) != 0;

                isInherited = isInherited && (inheritedObjectType == "00000000-0000-0000-0000-000000000000" ||
                                              inheritedObjectType == "bf967aa5-0de6-11d0-a285-00aa003049e2");

                //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;

                _guidMap.TryGetValue(guid, out var mappedGuid);

                //Interesting OU ACEs - GenericAll, GenericWrite, WriteDacl, WriteOwner,
                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("WriteProperty"))
                {
                    toContinue |= guid.Equals("00000000-0000-0000-0000-000000000000") ||
                                  guid.Equals("f30e3bbe-9ff0-11d1-b603-0000f80367c1") || guid.Equals("") ||
                                  toContinue;
                }

                if (!toContinue)
                {
                    continue;
                }

                if (adRightString.Contains("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 (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 (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();
        }
Exemple #5
0
        public static void GetGroupInfo(SearchResultEntry entry, ResolvedEntry resolved, string domainSid, ref Group u)
        {
            if (!Utils.IsMethodSet(ResolvedCollectionMethod.Group))
            {
                return;
            }

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

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

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

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

                while (true)
                {
                    var top   = bottom + 1499;
                    var range = $"member;range={bottom}-{top}";
                    bottom += 1500;
                    //Try ranged retrieval
                    var result = _utils.DoSearch("(objectclass=*)", SearchScope.Base, new[] { range },
                                                 principalDomainName,
                                                 entry.DistinguishedName).DefaultIfEmpty(null).FirstOrDefault();

                    //We didn't get an object back. Break out of the loop
                    if (result?.Attributes.AttributeNames == null)
                    {
                        break;
                    }
                    var en = result.Attributes.AttributeNames.GetEnumerator();

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

                    if (en.Current == null)
                    {
                        continue;
                    }
                    var attrib = en.Current.ToString();
                    if (attrib.EndsWith("-*"))
                    {
                        //We're done here, no more members to grab
                        break;
                    }
                    tempMembers.AddRange(result.GetPropArray(attrib));
                }

                members = tempMembers.ToArray();
            }

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

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

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

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

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

            u.Members = fMembers.Distinct().ToArray();
        }
Exemple #6
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"));
        }