Skip to content

Commit 4cb3b41

Browse files
committed
Resolve all computer dns_hostnames of all sids that have full controle over the sccm object
1 parent 018ad9d commit 4cb3b41

1 file changed

Lines changed: 41 additions & 100 deletions

File tree

nxc/modules/sccm.py

Lines changed: 41 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -9,84 +9,6 @@
99
SAM_MACHINE_ACCOUNT = 0x30000001
1010
SAM_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

9113
class 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

Comments
 (0)