mirror of https://github.com/daffainfo/nuclei.git
implement enumeration methods + rewrite kerberoastable
parent
89d30d94d6
commit
9d23f5f88f
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue