99SAM_MACHINE_ACCOUNT = 0x30000001
1010SAM_GROUP_OBJECT = 0x10000000
1111
12- # Universal SIDs
13- WELL_KNOWN_SIDS = {
14- "S-1-0" : "Null Authority" ,
15- "S-1-0-0" : "Nobody" ,
16- "S-1-1" : "World Authority" ,
17- "S-1-1-0" : "Everyone" ,
18- "S-1-2" : "Local Authority" ,
19- "S-1-2-0" : "Local" ,
20- "S-1-2-1" : "Console Logon" ,
21- "S-1-3" : "Creator Authority" ,
22- "S-1-3-0" : "Creator Owner" ,
23- "S-1-3-1" : "Creator Group" ,
24- "S-1-3-2" : "Creator Owner Server" ,
25- "S-1-3-3" : "Creator Group Server" ,
26- "S-1-3-4" : "Owner Rights" ,
27- "S-1-5-80-0" : "All Services" ,
28- "S-1-4" : "Non-unique Authority" ,
29- "S-1-5" : "NT Authority" ,
30- "S-1-5-1" : "Dialup" ,
31- "S-1-5-2" : "Network" ,
32- "S-1-5-3" : "Batch" ,
33- "S-1-5-4" : "Interactive" ,
34- "S-1-5-6" : "Service" ,
35- "S-1-5-7" : "Anonymous" ,
36- "S-1-5-8" : "Proxy" ,
37- "S-1-5-9" : "Enterprise Domain Controllers" ,
38- "S-1-5-10" : "Principal Self" ,
39- "S-1-5-11" : "Authenticated Users" ,
40- "S-1-5-12" : "Restricted Code" ,
41- "S-1-5-13" : "Terminal Server Users" ,
42- "S-1-5-14" : "Remote Interactive Logon" ,
43- "S-1-5-15" : "This Organization" ,
44- "S-1-5-17" : "This Organization" ,
45- "S-1-5-18" : "Local System" ,
46- "S-1-5-19" : "NT Authority" ,
47- "S-1-5-20" : "NT Authority" ,
48- "S-1-5-32-544" : "Administrators" ,
49- "S-1-5-32-545" : "Users" ,
50- "S-1-5-32-546" : "Guests" ,
51- "S-1-5-32-547" : "Power Users" ,
52- "S-1-5-32-548" : "Account Operators" ,
53- "S-1-5-32-549" : "Server Operators" ,
54- "S-1-5-32-550" : "Print Operators" ,
55- "S-1-5-32-551" : "Backup Operators" ,
56- "S-1-5-32-552" : "Replicators" ,
57- "S-1-5-64-10" : "NTLM Authentication" ,
58- "S-1-5-64-14" : "SChannel Authentication" ,
59- "S-1-5-64-21" : "Digest Authority" ,
60- "S-1-5-80" : "NT Service" ,
61- "S-1-5-83-0" : "NT VIRTUAL MACHINE\\ Virtual Machines" ,
62- "S-1-16-0" : "Untrusted Mandatory Level" ,
63- "S-1-16-4096" : "Low Mandatory Level" ,
64- "S-1-16-8192" : "Medium Mandatory Level" ,
65- "S-1-16-8448" : "Medium Plus Mandatory Level" ,
66- "S-1-16-12288" : "High Mandatory Level" ,
67- "S-1-16-16384" : "System Mandatory Level" ,
68- "S-1-16-20480" : "Protected Process Mandatory Level" ,
69- "S-1-16-28672" : "Secure Process Mandatory Level" ,
70- "S-1-5-32-554" : "BUILTIN\\ Pre-Windows 2000 Compatible Access" ,
71- "S-1-5-32-555" : "BUILTIN\\ Remote Desktop Users" ,
72- "S-1-5-32-557" : "BUILTIN\\ Incoming Forest Trust Builders" ,
73- "S-1-5-32-556" : "BUILTIN\\ Network Configuration Operators" ,
74- "S-1-5-32-558" : "BUILTIN\\ Performance Monitor Users" ,
75- "S-1-5-32-559" : "BUILTIN\\ Performance Log Users" ,
76- "S-1-5-32-560" : "BUILTIN\\ Windows Authorization Access Group" ,
77- "S-1-5-32-561" : "BUILTIN\\ Terminal Server License Servers" ,
78- "S-1-5-32-562" : "BUILTIN\\ Distributed COM Users" ,
79- "S-1-5-32-569" : "BUILTIN\\ Cryptographic Operators" ,
80- "S-1-5-32-573" : "BUILTIN\\ Event Log Readers" ,
81- "S-1-5-32-574" : "BUILTIN\\ Certificate Service DCOM Access" ,
82- "S-1-5-32-575" : "BUILTIN\\ RDS Remote Access Servers" ,
83- "S-1-5-32-576" : "BUILTIN\\ RDS Endpoint Servers" ,
84- "S-1-5-32-577" : "BUILTIN\\ RDS Management Servers" ,
85- "S-1-5-32-578" : "BUILTIN\\ Hyper-V Administrators" ,
86- "S-1-5-32-579" : "BUILTIN\\ Access Control Assistance Operators" ,
87- "S-1-5-32-580" : "BUILTIN\\ Remote Management Users" ,
88- }
89-
9012
9113class NXCModule :
9214 """
@@ -103,7 +25,7 @@ class NXCModule:
10325 multiple_hosts = True
10426
10527 def __init__ (self ):
106- self .sAMAccountNames = []
28+ self .sccm_sites = []
10729 self .base_dn = ""
10830
10931 def options (self , context , module_options ):
@@ -137,56 +59,75 @@ def on_login(self, context, connection):
13759 principal_security_descriptor = ldaptypes .SR_SECURITY_DESCRIPTOR (data = raw_sec_descriptor )
13860 context .log .highlight (f"Found SCCM object: { item [0 ]} " )
13961 self .parse_dacl (principal_security_descriptor ["Dacl" ])
140- self .context .log .highlight (f"Found sAMAccountNames: { self .sAMAccountNames } " )
141-
62+ self .context .log .highlight (f"Found sccm_sites: { self .sccm_sites } " )
14263
14364 except LDAPSearchError as e :
14465 context .log .fail (f"Obtained unexpected exception: { e } " )
14566
14667 def parse_dacl (self , dacl ):
147- """Parses a DACL and extracts the sAMAccountNames with full control."""
148- parsed_dacl = []
68+ """Parses a DACL and extracts the dns host names with full control over the SCCM object."""
14969 self .context .log .debug ("Parsing DACL" )
15070 for ace in dacl ["Data" ]:
151- parsed_ace = self .parse_ace (ace )
152- parsed_dacl .append (parsed_ace )
71+ self .parse_ace (ace )
15372
15473 def parse_ace (self , ace ):
155- """Parses an ACE and appends the sAMAccountName to the list of known sAMAccountNames if the SID of the ACE has full control."""
74+ """Parses an ACE and resolves the SID if the SID of the ACE has full control."""
15675 if ace ["TypeName" ] in ["ACCESS_ALLOWED_ACE" , "ACCESS_ALLOWED_OBJECT_ACE" ]:
15776 ace = ace ["Ace" ]
15877 sid = ace ["Sid" ].formatCanonical ()
15978 mask = ace ["Mask" ]
16079 fullcontrol = 0xf01ff
16180 if mask .hasPriv (fullcontrol ):
162- self .context .log .debug (f"Full control for { sid } " )
163- print (f"SID: { sid } , sAMAccountName: { self .resolveSID (sid )} " )
164- self .sAMAccountNames .append (str (self .resolveSID (sid )))
81+ self .resolve_SID (sid )
16582
166- def resolveSID (self , sid ) -> str :
167- """Tries to resolve a SID and returns the corresponding sAMAccountName if found ."""
83+ def resolve_SID (self , sid ):
84+ """Tries to resolve a SID and add the dNSHostName to the sccm site list ."""
16885 try :
86+ self .context .log .debug (f"Resolving SID: { sid } " )
16987 result = self .connection .ldapConnection .search (
17088 searchBase = self .base_dn ,
17189 searchFilter = f"(objectSid={ sid } )" ,
17290 attributes = ["sAMAccountName" , "sAMAccountType" , "member" , "dNSHostName" ],
17391 )
17492 parsed_result = parse_result_attributes (result )
17593 if not parsed_result :
176- return ""
94+ return None
17795 else :
178- parsed_result = parsed_result [0 ]
96+ parsed_result = parsed_result [0 ] # We only have one result as we always query a single SID
17997
18098 if int (parsed_result ["sAMAccountType" ]) == SAM_MACHINE_ACCOUNT :
181- print (f"{ parsed_result ['sAMAccountName ' ]} IS MACHINE ACCOUNT " )
182- return parsed_result ["sAMAccountName" ]
99+ self . context . log . debug (f"Found object with full control over SCCM object. SID: { sid } , dns_hostname: { parsed_result ['dNSHostName ' ]} " )
100+ self . sccm_sites . append ( parsed_result ["dNSHostName" ])
183101 elif int (parsed_result ["sAMAccountType" ]) == SAM_GROUP_OBJECT :
184- print (f"{ parsed_result ['sAMAccountName' ]} IS GROUP OBJECT" )
185- print (parsed_result ["member" ])
186- return ""
187-
102+ if isinstance (parsed_result ["member" ], list ):
103+ for member in parsed_result ["member" ]:
104+ member_sid = self .dn_to_sid (member )
105+ if member_sid :
106+ self .resolve_SID (member_sid )
107+ else : # Group has only one member
108+ member_sid = self .dn_to_sid (parsed_result ["member" ])
109+ if member_sid :
110+ self .resolve_SID (member_sid )
188111
189112 except Exception as e :
190- print (e .with_traceback ())
191113 self .context .log .debug (f"SID not found in LDAP: { sid } , { e } " )
192114 return ""
115+
116+ def dn_to_sid (self , dn ) -> str :
117+ """Tries to resolve a DN to a SID."""
118+ try :
119+ result = self .connection .ldapConnection .search (
120+ searchBase = self .base_dn ,
121+ searchFilter = f"(distinguishedName={ dn } )" ,
122+ attributes = ["sAMAccountName" , "objectSid" ],
123+ )
124+ parsed_result = parse_result_attributes (result )[0 ]
125+ self .context .log .highlight (f"Found object for DN { dn } : { parsed_result [0 ]} " )
126+ if not parsed_result :
127+ return ""
128+ else :
129+ parsed_result = parsed_result [0 ]
130+ return parsed_result ["objectSid" ]
131+ except Exception as e :
132+ self .context .log .debug (f"DN not found in LDAP: { dn } , { e } " )
133+ return ""
0 commit comments