forked from synacktiv/ntdissector
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support of msDS-AllowedToActOnBehalfOfOtherIdentity, pwdLastSet…
… and status on user_to_secretsdump.py
- Loading branch information
wilfried
committed
Sep 27, 2023
1 parent
9b11856
commit 60a36c3
Showing
5 changed files
with
270 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
A module used to handle binary ntSecurityDescriptor from Active Directory LDAP. | ||
""" | ||
|
||
from struct import unpack | ||
|
||
from ldap3.protocol.formatters.formatters import format_sid, format_uuid_le | ||
|
||
SDDLTypeFlags = { | ||
'Self Relative' : 0b1000000000000000, | ||
'RM Control Valid' : 0b0100000000000000, | ||
'SACL Protected' : 0b0010000000000000, | ||
'DACL Protected' : 0b0001000000000000, | ||
'SACL Auto Inherit' : 0b0000100000000000, | ||
'DACL Auto Inherit' : 0b0000010000000000, | ||
'SACL Auto Inherit Required' : 0b0000001000000000, | ||
'DACL Auto Inherit Required' : 0b0000000100000000, | ||
'Server Security' : 0b0000000010000000, | ||
'DACL Trusted' : 0b0000000001000000, | ||
'SACL Defaulted' : 0b0000000000100000, | ||
'SACL Present' : 0b0000000000010000, | ||
'DACL Defaulted' : 0b0000000000001000, | ||
'DACL Present' : 0b0000000000000100, | ||
'Group Defaulted' : 0b0000000000000010, | ||
'Owner Defaulted' : 0b0000000000000001, | ||
} | ||
|
||
SID_SIZE = 28 | ||
|
||
|
||
def parse_ntSecurityDescriptor(input_buffer): | ||
""" Parses a ntSecurityDescriptor. | ||
""" | ||
out = dict() | ||
fields = ('Revision', 'Raw Type', 'Offset to owner SID', 'Offset to group SID', 'Offset to SACL', 'Offset to DACL') | ||
|
||
for k, v in zip(fields, unpack('<HHIIII', input_buffer[:20])): | ||
out[k] = v | ||
|
||
out['Type'] = parse_sddl_type(out['Raw Type']) | ||
|
||
for x in ('Owner', 'Group'): | ||
offset = out['Offset to %s SID' % (x.lower())] | ||
out['%s SID' % x] = format_sid(input_buffer[offset:offset + SID_SIZE]) | ||
|
||
if out['Type']['SACL Present']: | ||
out['SACL'] = parse_acl(input_buffer[out['Offset to SACL']:]) | ||
|
||
if out['Type']['DACL Present']: | ||
out['DACL'] = parse_acl(input_buffer[out['Offset to DACL']:]) | ||
|
||
return out | ||
|
||
|
||
def resolve_flags(bfr, flags): | ||
""" | ||
Helper to resolve flag values and names. | ||
Arguments: | ||
#bfr:integer | ||
The buffer containing flags. | ||
#flags:dict | ||
The dictionary of flag names and values. | ||
""" | ||
return {k: v & bfr != 0 for k, v in flags.items()} | ||
|
||
|
||
def parse_sddl_type(typeflags): | ||
""" | ||
Parses SDDL Type flags. | ||
""" | ||
return resolve_flags(typeflags, SDDLTypeFlags) | ||
|
||
|
||
def parse_acl(input_buffer): | ||
""" | ||
Parses ACL from SDDL. | ||
Returns a list of ACEs. | ||
""" | ||
out = dict() | ||
fields = ('Revision', 'Size', 'Num ACEs') | ||
|
||
for k, v in zip(fields, unpack('<HHI', input_buffer[:8])): | ||
out[k] = v | ||
|
||
out['ACEs'] = parse_aces(input_buffer[8:8 + out['Size']], out['Num ACEs']) | ||
return out | ||
|
||
|
||
def parse_aces(input_buffer, count): | ||
""" | ||
Parses the list of ACEs. | ||
""" | ||
out = [] | ||
while len(out) < count: | ||
ace = dict() | ||
fields = ('Raw Type', 'Raw Flags', 'Size', 'Raw Access Required') | ||
for k, v in zip(fields, unpack('<BBHI', input_buffer[:8])): | ||
ace[k] = v | ||
|
||
ace['Type'] = parse_sddl_dacl_ace_type(ace['Raw Type']) | ||
|
||
ace['Access Required'] = parse_ace_access(ace['Raw Access Required']) | ||
|
||
offset = 8 | ||
|
||
if ace['Type'].endswith('Object'): | ||
fields = ('Raw Object Flags', ) | ||
for k, v in zip(fields, unpack('<I', input_buffer[8:12])): | ||
ace[k] = v | ||
ace['Object Flags'] = parse_ace_object_flags(ace['Raw Object Flags']) | ||
|
||
offset = 12 | ||
if ace['Object Flags']['Object Type Present']: | ||
ace['GUID'] = format_uuid_le(input_buffer[offset:offset + 16]) | ||
offset += 16 | ||
if ace['Object Flags']['Inherited Object Type Present']: | ||
ace['Inherited GUID'] = format_uuid_le(input_buffer[offset:offset + 16]) | ||
offset += 16 | ||
|
||
ace['SID'] = format_sid(input_buffer[offset:ace['Size']]) | ||
|
||
ace['SID'] = format_sid(input_buffer[offset:ace['Size']]) | ||
|
||
input_buffer = input_buffer[ace['Size']:] | ||
|
||
out.append(ace) | ||
return out | ||
|
||
|
||
ACEAccessFlags = { | ||
'Generic Read' : 0b10000000000000000000000000000000, | ||
'Generic Write' : 0b01000000000000000000000000000000, | ||
'Generic Execute' : 0b00100000000000000000000000000000, | ||
'Generic All' : 0b00010000000000000000000000000000, | ||
'Maximum Allowed' : 0b00000010000000000000000000000000, | ||
'Access SACL' : 0b00000000100000000000000000000000, | ||
'Synchronise' : 0b00000000000100000000000000000000, | ||
'Write Owner' : 0b00000000000010000000000000000000, | ||
'Write DAC' : 0b00000000000001000000000000000000, | ||
'Read Control' : 0b00000000000000100000000000000000, | ||
'Delete' : 0b00000000000000010000000000000000, | ||
'Ads Control Access' : 0b00000000000000000000000100000000, | ||
'Ads List Object' : 0b00000000000000000000000010000000, | ||
'Ads Delete Tree' : 0b00000000000000000000000001000000, | ||
'Ads Write Prop' : 0b00000000000000000000000000100000, | ||
'Ads Read Prop' : 0b00000000000000000000000000010000, | ||
'Ads Self Write' : 0b00000000000000000000000000001000, | ||
'Ads List' : 0b00000000000000000000000000000100, | ||
'Ads Delete Child' : 0b00000000000000000000000000000010, | ||
'Ads Create Child' : 0b00000000000000000000000000000001 | ||
} | ||
|
||
|
||
def parse_ace_access(input_buffer): | ||
""" | ||
Parses access flags in an ACE. | ||
""" | ||
return resolve_flags(input_buffer, ACEAccessFlags) | ||
|
||
|
||
ACEObjectFlags = { | ||
'Object Type Present' : 0b00000000000000000000000000000010, | ||
'Inherited Object Type Present' : 0b00000000000000000000000000000001 | ||
} | ||
|
||
|
||
def parse_ace_object_flags(input_buffer): | ||
""" | ||
Parses flags in an ACE containing an object. | ||
""" | ||
return resolve_flags(input_buffer, ACEObjectFlags) | ||
|
||
|
||
ACEType = { | ||
0x00: 'Access Allowed', | ||
0x01: 'Access Denied', | ||
0x02: 'System Audit', | ||
0x03: 'System Alarm', | ||
0x04: 'Access Allowed Compound', | ||
0x05: 'Access Allowed Object', | ||
0x06: 'Access Denied Object', | ||
0x07: 'System Audit Object', | ||
0x08: 'System Alarm Object', | ||
0x09: 'Access Allowed Callback', | ||
0x0A: 'Access Denied Callback', | ||
0x0B: 'Access Allowed Callback Object', | ||
0x0C: 'Access Denied Callback Object', | ||
0x0D: 'System Audit Callback', | ||
0x0E: 'System Alarm Callback', | ||
0x0F: 'System Audit Callback Object', | ||
0x10: 'System Alarm Callback Object', | ||
0x11: 'System Mandatory Label', | ||
0x12: 'System Resource Attribute', | ||
0x13: 'System Scoped Policy ID' | ||
} | ||
|
||
|
||
def parse_sddl_dacl_ace_type(ace_type): | ||
""" | ||
Parses the type of an ACE. | ||
""" | ||
return ACEType[ace_type] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,5 @@ python_dateutil==2.8.2 | |
pyasn1-modules>=0.3.0 | ||
six | ||
termcolor | ||
tqdm>=4.65 | ||
tqdm>=4.65 | ||
ldap3 |