Skip to content
This repository has been archived by the owner on Dec 6, 2023. It is now read-only.

[LDAP] Query for user groups or group members #803

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions cme/protocols/ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1429,3 +1429,106 @@ def bloodhound(self):
if each_file.startswith(timestamp) and each_file.endswith("json"):
z.write(each_file)
os.remove(each_file)

def get_user_groups(self):
# Initialize the distinguishedName variable
distinguishedName = None

# Building the search filter
search_filter = f"(&(sAMAccountName={self.args.get_user_groups})(objectclass=user))"
# Only grab the distinguishedName
attributes = [
"distinguishedName"
]

resp = self.search(search_filter, attributes, sizeLimit=0)
if resp:
answers = []
for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
continue
try:
for attribute in item["attributes"]:
if str(attribute["type"]) == "distinguishedName":
distinguishedName = str(attribute["vals"][0])
except Exception as e:
self.logger.debug(f"Skipping item, cannot process due to error {e}")
pass

# If the distinguishedName is still None, fail
if distinguishedName == None:
self.logger.fail("User does not exist.")
return

# Search for groups assigned to distinguishedName
search_filter = f"(&(objectClass=group)(member={distinguishedName}))"
attributes = [
"cn"
]
resp = self.search(search_filter, attributes, sizeLimit=0)
if resp:
answers = []
for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
continue
commonName = ""
try:
for attribute in item["attributes"]:
if str(attribute["type"]) == "cn":
commonName = str(attribute["vals"][0])
self.logger.highlight(f"{commonName:<30}")
except Exception as e:
self.logger.debug(f"Skipping item, cannot process due to error {e}")
pass

def get_group_users(self):
# Initialize the distinguishedName variable
distinguishedName = None

# Building the search filter
search_filter = f"(&(cn={self.args.get_group_users})(objectclass=group))"
# Only grab the distinguishedName
attributes = [
"distinguishedName"
]

resp = self.search(search_filter, attributes, sizeLimit=0)
if resp:
answers = []
for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
continue
try:
for attribute in item["attributes"]:
if str(attribute["type"]) == "distinguishedName":
distinguishedName = str(attribute["vals"][0])
except Exception as e:
self.logger.debug(f"Skipping item, cannot process due to error {e}")
pass

# If the distinguishedName is still None, fail
if distinguishedName == None:
self.logger.fail("Group does not exist.")
return

# Search for groups assigned to distinguishedName
search_filter = f"(&(objectClass=user)(memberOf={distinguishedName}))"
# Only search for the sAMAccountName
attributes = [
"sAMAccountName"
]
resp = self.search(search_filter, attributes, sizeLimit=0)
if resp:
answers = []
for item in resp:
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
continue
sAMAccountName = ""
try:
for attribute in item["attributes"]:
if str(attribute["type"]) == "sAMAccountName":
sAMAccountName = str(attribute["vals"][0])
self.logger.highlight(f"{sAMAccountName:<30}")
except Exception as e:
self.logger.debug(f"Skipping item, cannot process due to error {e}")
pass
4 changes: 3 additions & 1 deletion cme/protocols/ldap/proto_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def proto_args(parser, std_parser, module_parser):
vgroup.add_argument("--groups", action="store_true", help="Enumerate domain groups")
vgroup.add_argument("--dc-list", action="store_true", help="Enumerate Domain Controllers")
vgroup.add_argument("--get-sid", action="store_true", help="Get domain sid")
vgroup.add_argument("--get-user-groups", help="Enumerate domain groups of a domain user (Example: --get-user-groups <username>)")
vgroup.add_argument("--get-group-users", help="Enumerate domain users of a domain group (Example: --get-group-users <groupName>)")

ggroup = ldap_parser.add_argument_group("Retrevie gmsa on the remote DC", "Options to play with gmsa")
ggroup.add_argument("--gmsa", action="store_true", help="Enumerate GMSA passwords")
Expand All @@ -48,4 +50,4 @@ def __call__(self, parser, namespace, values, option_string=None):
x.required = True
super(ConditionalAction, self).__call__(parser, namespace, values, option_string)

return ConditionalAction
return ConditionalAction