From 9d23f5f88f6156e28697d80b1e1906d72ab1d2c2 Mon Sep 17 00:00:00 2001 From: 5amu Date: Sun, 21 Jan 2024 17:11:28 +0100 Subject: [PATCH] implement enumeration methods + rewrite kerberoastable --- pkg/js/libs/ldap/adenum.go | 36 ++++++++++++++++++++++ pkg/js/libs/ldap/ldap.go | 61 +------------------------------------- 2 files changed, 37 insertions(+), 60 deletions(-) diff --git a/pkg/js/libs/ldap/adenum.go b/pkg/js/libs/ldap/adenum.go index db8da6e7..a0551b17 100644 --- a/pkg/js/libs/ldap/adenum.go +++ b/pkg/js/libs/ldap/adenum.go @@ -53,3 +53,39 @@ func (c *LdapClient) FindADObjects(filter string) ([]ADObject, error) { } return objects, nil } + +func (c *LdapClient) GetADUsers() ([]ADObject, error) { + return c.FindADObjects(FilterIsPerson) +} + +func (c *LdapClient) GetADActiveUsers() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled)) +} + +func (c *LdapClient) GetADUserWithNeverExpiringPasswords() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterDontExpirePassword)) +} + +func (c *LdapClient) GetADUserTrustedForDelegation() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterTrustedForDelegation)) +} + +func (c *LdapClient) GetADUserWithPasswordNotRequired() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterPasswordNotRequired)) +} + +func (c *LdapClient) GetADGroups() ([]ADObject, error) { + return c.FindADObjects(FilterIsGroup) +} + +func (c *LdapClient) GetADDCList() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsComputer, FilterAccountEnabled, FilterServerTrustAccount)) +} + +func (c *LdapClient) GetADAdmins() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled, FilterIsAdmin)) +} + +func (c *LdapClient) GetADUserKerberoastable() ([]ADObject, error) { + return c.FindADObjects(JoinFilters(FilterIsPerson, FilterAccountEnabled, FilterHasServicePrincipalName)) +} diff --git a/pkg/js/libs/ldap/ldap.go b/pkg/js/libs/ldap/ldap.go index 38b733b5..02f5900b 100644 --- a/pkg/js/libs/ldap/ldap.go +++ b/pkg/js/libs/ldap/ldap.go @@ -119,6 +119,7 @@ const ( FilterIsGroup = "(objectCategory=group)" FilterIsComputer = "(objectCategory=computer)" FilterIsAdmin = "(adminCount=1)" + FilterHasServicePrincipalName = "(servicePrincipalName=*)" FilterLogonScript = "(userAccountControl:1.2.840.113556.1.4.803:=1)" // The logon script will be run. FilterAccountDisabled = "(userAccountControl:1.2.840.113556.1.4.803:=2)" // The user account is disabled. FilterAccountEnabled = "(!(userAccountControl:1.2.840.113556.1.4.803:=2))" // The user account is enabled. @@ -255,63 +256,3 @@ func (c *LdapClient) CollectMetadata(domain string, controller string) (Metadata } return metadata, nil } - -// KerberoastableUser contains the important fields of the Active Directory -// kerberoastable user -type KerberoastableUser struct { - SAMAccountName string - ServicePrincipalName string - PWDLastSet string - MemberOf string - UserAccountControl string - LastLogon string -} - -// GetKerberoastableUsers collects all "person" users that have an SPN -// associated with them. The LDAP filter is built with the same logic as -// "GetUserSPNs.py", the well-known impacket example by Forta. -// https://github.com/fortra/impacket/blob/master/examples/GetUserSPNs.py#L297 -// -// Returns a list of KerberoastableUser, if an error occurs, returns an empty -// slice and the raised error -func (c *LdapClient) GetKerberoastableUsers(domain, controller string, username, password string) ([]KerberoastableUser, error) { - sr := ldap.NewSearchRequest( - c.BaseDN, - ldap.ScopeWholeSubtree, - ldap.NeverDerefAliases, - 0, 0, false, - // (&(is_user) (!(account_is_disabled)) (has_SPN)) - "(&(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(servicePrincipalName=*))", - []string{ - "SAMAccountName", - "ServicePrincipalName", - "pwdLastSet", - "MemberOf", - "userAccountControl", - "lastLogon", - }, - nil, - ) - - res, err := c.Conn.Search(sr) - if err != nil { - return nil, err - } - - if len(res.Entries) == 0 { - return nil, fmt.Errorf("no kerberoastable user found") - } - - var ku []KerberoastableUser - for _, usr := range res.Entries { - ku = append(ku, KerberoastableUser{ - SAMAccountName: usr.GetAttributeValue("sAMAccountName"), - ServicePrincipalName: usr.GetAttributeValue("servicePrincipalName"), - PWDLastSet: usr.GetAttributeValue("pwdLastSet"), - MemberOf: usr.GetAttributeValue("MemberOf"), - UserAccountControl: usr.GetAttributeValue("userAccountControl"), - LastLogon: usr.GetAttributeValue("lastLogon"), - }) - } - return ku, nil -}