Skip to content

Commit 7db7de4

Browse files
authored
Update ldap.py.
Added processAttributeValue Function A new helper function was introduced to process the content of LDAP AttributeValue objects. Updated printTable Function Resource-Based Constrained Delegation Processing Added Constant Variables Constant variables were defined for userAccountControl values. Modular Code Structure The overall structure was made more modular; functions were clearly separated for better readability. Signed-off-by: termanix <50464194+termanix@users.noreply.github.com>
1 parent 509f6d1 commit 7db7de4

1 file changed

Lines changed: 52 additions & 45 deletions

File tree

nxc/protocols/ldap.py

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,55 +1087,62 @@ def query(self):
10871087
self.logger.highlight(f"{attr:<20} {vals}")
10881088

10891089
def find_delegation(self):
1090+
# Constants for delegation types
1091+
UF_TRUSTED_FOR_DELEGATION = 0x80000
1092+
UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x1000000
1093+
UF_ACCOUNTDISABLE = 0x2
1094+
1095+
def processAttributeValue(attribute):
1096+
# Extract the payload value from the AttributeValue object
1097+
if hasattr(attribute, "payload"):
1098+
return str(attribute.payload)
1099+
return str(attribute)
1100+
10901101
def printTable(items, header):
10911102
colLen = []
1092-
try:
1093-
for i, col in enumerate(header):
1094-
rowMaxLen = max(len(str(row[i])) for row in items)
1095-
colLen.append(max(rowMaxLen, len(col)))
1103+
for i, col in enumerate(header):
1104+
rowMaxLen = max(len(str(row[i])) for row in items)
1105+
colLen.append(max(rowMaxLen, len(col)))
10961106

1097-
# Create the format string for each row
1098-
outputFormat = " ".join([f"{{{num}:{width}s}}" for num, width in enumerate(colLen)])
1107+
# Create the format string for each row
1108+
outputFormat = " ".join([f"{{{num}:{width}s}}" for num, width in enumerate(colLen)])
10991109

1100-
# Print header
1101-
self.logger.highlight(outputFormat.format(*header))
1102-
self.logger.highlight(" ".join(["-" * itemLen for itemLen in colLen]))
1110+
self.logger.highlight(outputFormat.format(*header))
1111+
self.logger.highlight(" ".join(["-" * itemLen for itemLen in colLen]))
11031112

1104-
# Print rows
1105-
for row in items:
1106-
self.logger.highlight(outputFormat.format(*row))
1107-
except Exception as e:
1108-
self.logger.fail("Header Index error " + str(e))
1113+
# Print rows
1114+
for row in items:
1115+
# Burada DelegationRightsTo'yu düzeltmek için join() ekleyin
1116+
row[3] = ", ".join(str(x) for x in row[3]) if isinstance(row[3], list) else row[3]
1117+
self.logger.highlight(outputFormat.format(*row))
11091118

11101119
# Building the search filter
1111-
search_filter = ("(&(|(UserAccountControl:1.2.840.113556.1.4.803:=16777216)(UserAccountControl:1.2.840.113556.1.4.803:="
1112-
"524288)(msDS-AllowedToDelegateTo=*)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))"
1113-
"(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(!(UserAccountControl:1.2.840.113556.1.4.803:=8192)))"
1114-
)
1115-
attributes = ["sAMAccountName",
1116-
"pwdLastSet",
1117-
"userAccountControl",
1118-
"objectCategory",
1119-
"msDS-AllowedToActOnBehalfOfOtherIdentity",
1120-
"msDS-AllowedToDelegateTo"]
1120+
search_filter = ("(&(|(UserAccountControl:1.2.840.113556.1.4.803:=16777216)"
1121+
"(UserAccountControl:1.2.840.113556.1.4.803:=524288)"
1122+
"(msDS-AllowedToDelegateTo=*)(msDS-AllowedToActOnBehalfOfOtherIdentity=*))"
1123+
"(!(UserAccountControl:1.2.840.113556.1.4.803:=2))"
1124+
"(!(UserAccountControl:1.2.840.113556.1.4.803:=8192)))")
11211125

1126+
attributes = ["sAMAccountName", "pwdLastSet", "userAccountControl", "objectCategory",
1127+
"msDS-AllowedToActOnBehalfOfOtherIdentity", "msDS-AllowedToDelegateTo"]
1128+
11221129
resp = self.search(search_filter, attributes, 0)
11231130

11241131
answers = []
11251132
self.logger.debug(f"Total of records returned {len(resp):d}")
11261133

11271134
for item in resp:
1128-
if isinstance(item, ldapasn1_impacket.SearchResultEntry) is not True:
1135+
if not isinstance(item, ldapasn1_impacket.SearchResultEntry):
11291136
continue
1137+
11301138
mustCommit = False
11311139
sAMAccountName = ""
11321140
userAccountControl = 0
11331141
delegation = ""
11341142
objectType = ""
11351143
rightsTo = []
11361144
protocolTransition = 0
1137-
1138-
# After receiving responses we parse through to determine the type of delegation configured on each object
1145+
11391146
try:
11401147
for attribute in item["attributes"]:
11411148
if str(attribute["type"]) == "sAMAccountName":
@@ -1154,42 +1161,42 @@ def printTable(items, header):
11541161
elif str(attribute["type"]) == "msDS-AllowedToDelegateTo":
11551162
if protocolTransition == 0:
11561163
delegation = "Constrained"
1157-
rightsTo = list(attribute["vals"])
1158-
1159-
# Not an elif as an object could both have rbcd and another type of delegation configured for the same object
1164+
rightsTo = [processAttributeValue(val) for val in attribute["vals"]]
1165+
1166+
# Not an elif as an object could both have RBCD and another type of delegation
11601167
if str(attribute["type"]) == "msDS-AllowedToActOnBehalfOfOtherIdentity":
11611168
rbcdRights = []
11621169
rbcdObjType = []
1163-
search_filter = "(&(|"
11641170
sd = ldaptypes.SR_SECURITY_DESCRIPTOR(data=bytes(attribute["vals"][0]))
1171+
search_filter = "(&(|"
11651172
for ace in sd["Dacl"].aces:
1166-
search_filter = search_filter + "(objectSid=" + ace["Ace"]["Sid"].formatCanonical() + ")"
1167-
search_filter = search_filter + ")(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))"
1173+
search_filter += "(objectSid=" + ace["Ace"]["Sid"].formatCanonical() + ")"
1174+
search_filter += ")(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))"
11681175
delegUserResp = self.search(search_filter, attributes=["sAMAccountName", "objectCategory"], sizeLimit=999)
1176+
11691177
for item2 in delegUserResp:
1170-
if isinstance(item2, ldapasn1_impacket.SearchResultEntry) is not True:
1178+
if not isinstance(item2, ldapasn1_impacket.SearchResultEntry):
11711179
continue
11721180
rbcdRights.append(str(item2["attributes"][0]["vals"][0]))
11731181
rbcdObjType.append(str(item2["attributes"][1]["vals"][0]).split("=")[1].split(",")[0])
1174-
1175-
if mustCommit is True:
1182+
1183+
if mustCommit:
11761184
if int(userAccountControl) & UF_ACCOUNTDISABLE:
1177-
self.logger.debug("Bypassing disabled account %s " % sAMAccountName)
1185+
self.logger.debug(f"Bypassing disabled account {sAMAccountName}")
11781186
else:
11791187
for rights, objType in zip(rbcdRights, rbcdObjType):
11801188
answers.append([rights, objType, "Resource-Based Constrained", sAMAccountName])
1181-
1182-
# Print unconstrained + constrained delegation relationships
1183-
if (delegation in ["Unconstrained", "Constrained", "Constrained w/ Protocol Transition"] and mustCommit):
1189+
1190+
if delegation in ["Unconstrained", "Constrained", "Constrained w/ Protocol Transition"] and mustCommit:
11841191
if int(userAccountControl) & UF_ACCOUNTDISABLE:
1185-
self.logger.debug("Bypassing disabled account %s " % sAMAccountName)
1192+
self.logger.debug(f"Bypassing disabled account {sAMAccountName}")
11861193
else:
1187-
answers = [sAMAccountName, objectType, delegation, rightsTo]
1194+
answers.append([sAMAccountName, objectType, delegation, rightsTo])
11881195

11891196
except Exception as e:
1190-
self.logger.error("Skipping item, cannot process due to error %s" % str(e))
1191-
1192-
if len(answers) > 0:
1197+
self.logger.error(f"Skipping item, cannot process due to error {e}")
1198+
1199+
if answers:
11931200
printTable(answers, header=["AccountName", "AccountType", "DelegationType", "DelegationRightsTo"])
11941201
else:
11951202
self.logger.fail("No entries found!")

0 commit comments

Comments
 (0)