@@ -683,30 +683,37 @@ def get_sid(self):
683683
684684 def check_if_admin (self ):
685685 # 1. get SID of the domaine
686- search_filter = "(userAccountControl:1.2.840.113556.1.4.803:=8192 )"
686+ search_filter = f "(userAccountControl:1.2.840.113556.1.4.803:={ UF_SERVER_TRUST_ACCOUNT } )"
687687 attributes = ["objectSid" ]
688- resp = self .search (search_filter , attributes , sizeLimit = 0 , baseDN = self .baseDN )
688+ resp = self .search (search_filter , attributes , baseDN = self .baseDN )
689689 resp_parsed = parse_result_attributes (resp )
690- answers = []
690+
691691 if resp and (self .password != "" or self .lmhash != "" or self .nthash != "" or self .aesKey != "" or self .use_kcache ) and self .username != "" :
692692 for item in resp_parsed :
693693 self .sid_domain = "-" .join (item ["objectSid" ].split ("-" )[:- 1 ])
694694
695695 # 2. get all group cn name
696- search_filter = f"(|(objectSid={ self .sid_domain } -512)(objectSid={ self .sid_domain } -544)(objectSid={ self .sid_domain } -519)(objectSid=S-1-5-32-549)(objectSid=S-1-5-32-551))"
696+ search_filter = (f"(|(objectSid={ self .sid_domain } -512)"
697+ f"(objectSid={ self .sid_domain } -519)"
698+ f"(objectSid={ self .sid_domain } -544)"
699+ "(objectSid=S-1-5-32-549)"
700+ "(objectSid=S-1-5-32-551))" )
697701 attributes = ["distinguishedName" ]
698- resp = self .search (search_filter , attributes , sizeLimit = 0 , baseDN = self .baseDN )
702+ resp = self .search (search_filter , attributes , baseDN = self .baseDN )
699703 resp_parsed = parse_result_attributes (resp )
700- answers = []
701- for item in resp_parsed :
702- answers .append (f"(memberOf:1.2.840.113556.1.4.1941:={ item ['distinguishedName' ]} )" )
704+ answers = [f"(memberOf:1.2.840.113556.1.4.1941:={ item ['distinguishedName' ]} )" for item in resp_parsed ]
703705 if len (answers ) == 0 :
704706 self .logger .debug ("No groups with default privileged RID were found. Assuming user is not a Domain Administrator." )
705707 return
706708
707- # 3. get member of these groups
709+ # 3. Build a filter to query if the primaryGroupID is one of these groups
710+ group_ids = ["512" , "519" , "544" , "549" , "551" ]
711+ primaryGroupID_filters = [f"(primaryGroupID={ group_id } )" for group_id in group_ids ]
712+ answers .extend (primaryGroupID_filters )
713+
714+ # 4. Check if the user is member of one of these groups OR has one of these primaryGroupID
708715 search_filter = f"(&(objectCategory=user)(sAMAccountName={ self .username } )(|{ '' .join (answers )} ))"
709- resp = self .search (search_filter , attributes = [], sizeLimit = 0 , baseDN = self .baseDN )
716+ resp = self .search (search_filter , attributes = [], baseDN = self .baseDN )
710717 resp_parsed = parse_result_attributes (resp )
711718 for item in resp_parsed :
712719 if item :
@@ -801,27 +808,39 @@ def groups(self):
801808 # Building the search filter
802809 if self .args .groups :
803810 self .logger .debug (f"Dumping group: { self .args .groups } " )
804- search_filter = f"(cn={ self .args .groups } )"
805- attributes = ["member" ]
811+
812+ # Resolve group DN and primaryGroupID (objectSid)
813+ group_resp = self .search (f"(cn={ self .args .groups } )" , ["distinguishedName" , "objectSid" ])
814+ group_parsed = parse_result_attributes (group_resp )
815+
816+ if not group_parsed :
817+ self .logger .fail (f"Group '{ self .args .groups } ' not found" )
818+ return
819+ else :
820+ group = group_parsed [0 ]
821+
822+ # Search filter: user must have membership OR primaryGroupID
823+ search_filter = f"(|(memberOf={ group ['distinguishedName' ]} )(primaryGroupID={ group ['objectSid' ].split ('-' )[- 1 ]} ))"
824+ attributes = ["sAMAccountName" , "distinguishedName" , "cn" , "objectClass" ]
825+
806826 else :
807827 search_filter = "(objectCategory=group)"
808828 attributes = ["cn" , "member" , "description" ]
809- resp = self .search (search_filter , attributes , 0 )
829+
830+ resp = self .search (search_filter , attributes )
810831 resp_parsed = parse_result_attributes (resp )
811832 self .logger .debug (f"Total of records returned { len (resp_parsed )} " )
812833
813834 if self .args .groups :
835+ # Display group members
814836 if not resp_parsed :
815- self .logger .fail (f"Group { self .args .groups } not found" )
816- elif not resp_parsed [0 ]:
817- self .logger .fail (f"Group { self .args .groups } has no members" )
837+ self .logger .fail (f"Group '{ self .args .groups } ' has no members" )
818838 else :
819- # Fix if group has only one member
820- if not isinstance (resp_parsed [0 ]["member" ], list ):
821- resp_parsed [0 ]["member" ] = [resp_parsed [0 ]["member" ]]
822- for user in resp_parsed [0 ]["member" ]:
823- self .logger .highlight (user .split ("," )[0 ].split ("=" )[1 ])
839+ for item in resp_parsed :
840+ # Display sAMAccountName or CN if sAMAccountName not present (could be a group)
841+ self .logger .highlight (item ["sAMAccountName" ] if "group" not in item ["objectClass" ] else item ["cn" ])
824842 else :
843+ # Display all groups
825844 self .logger .highlight (f"{ '-Group-' :<40} { '-Members-' :<9} { '-Description-' :<60} " )
826845 for item in resp_parsed :
827846 try :
@@ -1297,7 +1316,7 @@ def password_not_required(self):
12971316 "sAMAccountName" ,
12981317 "userAccountControl" ,
12991318 ]
1300- resp = self .search (searchFilter , attributes , sizeLimit = 0 , baseDN = self .baseDN )
1319+ resp = self .search (searchFilter , attributes , baseDN = self .baseDN )
13011320 resp_parsed = parse_result_attributes (resp )
13021321 self .logger .debug (f"Total of records returned { len (resp_parsed ):d} " )
13031322
@@ -1478,10 +1497,10 @@ def pso_mins(ldap_time):
14781497 # Let's find out even more details!
14791498 self .logger .info ("Attempting to enumerate details...\n " )
14801499 resp = self .search (searchFilter = "(objectclass=msDS-PasswordSettings)" ,
1481- attributes = ["name" , "msds-lockoutthreshold" , "msds-psoappliesto" , "msds-minimumpasswordlength" ,
1482- "msds-passwordhistorylength" , "msds-lockoutobservationwindow" , "msds-lockoutduration" ,
1483- "msds-passwordsettingsprecedence" , "msds-passwordcomplexityenabled" , "Description" ,
1484- "msds-passwordreversibleencryptionenabled" , "msds-minimumpasswordage" , "msds-maximumpasswordage" ])
1500+ attributes = ["name" , "msds-lockoutthreshold" , "msds-psoappliesto" , "msds-minimumpasswordlength" ,
1501+ "msds-passwordhistorylength" , "msds-lockoutobservationwindow" , "msds-lockoutduration" ,
1502+ "msds-passwordsettingsprecedence" , "msds-passwordcomplexityenabled" , "Description" ,
1503+ "msds-passwordreversibleencryptionenabled" , "msds-minimumpasswordage" , "msds-maximumpasswordage" ])
14851504 resp_parsed = parse_result_attributes (resp )
14861505 for attrs in resp_parsed :
14871506 policyName = attrs .get ("name" , "" )
@@ -1534,7 +1553,7 @@ def pass_pol(self):
15341553 "pwdProperties"
15351554 ]
15361555
1537- resp = self .search (search_filter , attributes , sizeLimit = 0 , baseDN = self .baseDN )
1556+ resp = self .search (search_filter , attributes , baseDN = self .baseDN )
15381557 resp_parsed = parse_result_attributes (resp )
15391558
15401559 if not resp_parsed :
0 commit comments