Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/fortra/impacket/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The ldaptypes module provides structures for working with Windows security descriptors, Access Control Lists (ACLs), and Security Identifiers (SIDs) in their LDAP/non-RPC binary format.

Security Identifiers

LDAP_SID

Represents a Security Identifier in LDAP format.
from impacket.ldap.ldaptypes import LDAP_SID

sid = LDAP_SID(data=binary_sid_data)
print(sid.formatCanonical())  # S-1-5-21-...

Methods

formatCanonical() Returns the SID in canonical string format.
sid_string = sid.formatCanonical()
# Returns: 'S-1-5-21-3623811015-3361044348-30300820-1013'
fromCanonical(canonical) Parse a canonical SID string into the structure.
sid = LDAP_SID()
sid.fromCanonical('S-1-5-21-3623811015-3361044348-30300820-1013')

Security Descriptors

SR_SECURITY_DESCRIPTOR

Self-relative security descriptor as defined in MS-DTYP 2.4.6.
from impacket.ldap.ldaptypes import SR_SECURITY_DESCRIPTOR

sd = SR_SECURITY_DESCRIPTOR(data=descriptor_bytes)

Structure Fields

  • Revision (byte): Descriptor revision (usually 1)
  • Control (short): Control flags
  • OwnerSid (LDAP_SID): Owner SID
  • GroupSid (LDAP_SID): Primary group SID
  • Sacl (ACL): System ACL
  • Dacl (ACL): Discretionary ACL

Example

# Read security descriptor from LDAP
result = conn.search(
    searchFilter='(sAMAccountName=admin)',
    attributes=['nTSecurityDescriptor']
)

for entry in result:
    for attr in entry['attributes']:
        if str(attr['type']) == 'nTSecurityDescriptor':
            sd_data = bytes(attr['vals'][0])
            sd = SR_SECURITY_DESCRIPTOR(data=sd_data)
            
            print(f"Owner: {sd['OwnerSid'].formatCanonical()}")
            print(f"Group: {sd['GroupSid'].formatCanonical()}")

Access Control Lists

ACL

Represents an Access Control List containing multiple ACEs.
from impacket.ldap.ldaptypes import ACL

acl = ACL(data=acl_bytes)
print(f"ACE Count: {acl['AceCount']}")

for ace in acl.aces:
    print(f"ACE Type: {ace['TypeName']}")
    print(f"SID: {ace['Ace']['Sid'].formatCanonical()}")

Structure Fields

  • AclRevision (byte): ACL revision
  • AceCount (short): Number of ACEs
  • aces (list): List of ACE objects

Access Control Entries

ACE

Base ACE structure. The actual ACE type is determined by the AceType field.
from impacket.ldap.ldaptypes import ACE

ace = ACE(data=ace_bytes)
print(f"Type: {ace['TypeName']}")
print(f"Flags: 0x{ace['AceFlags']:02x}")

ACE Flags

from impacket.ldap.ldaptypes import ACE

CONTAINER_INHERIT_ACE = 0x02
INHERIT_ONLY_ACE = 0x08
INHERITED_ACE = 0x10
OBJECT_INHERIT_ACE = 0x01

if ace.hasFlag(ACE.CONTAINER_INHERIT_ACE):
    print("ACE inherits to child containers")

ACCESS_ALLOWED_ACE

Grants access rights to a trustee.
from impacket.ldap.ldaptypes import ACCESS_ALLOWED_ACE

# ACE Type: 0x00
ace_data = ace['Ace']  # Parsed from ACE
mask = ace_data['Mask']
sid = ace_data['Sid']

print(f"Allowed rights: 0x{mask['Mask']:08x}")
print(f"Trustee: {sid.formatCanonical()}")

ACCESS_ALLOWED_OBJECT_ACE

Object-specific access control for Active Directory.
from impacket.ldap.ldaptypes import ACCESS_ALLOWED_OBJECT_ACE

# ACE Type: 0x05
ace_data = ace['Ace']

if ace_data.hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT):
    # ObjectType is a GUID identifying the property/extended right
    object_guid = ace_data['ObjectType']
    print(f"Object GUID: {object_guid.hex()}")

if ace_data.hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_INHERITED_OBJECT_TYPE_PRESENT):
    # Inherited object type
    inherited_guid = ace_data['InheritedObjectType']

Object ACE Rights

from impacket.ldap.ldaptypes import ACCESS_ALLOWED_OBJECT_ACE

ADS_RIGHT_DS_CONTROL_ACCESS = 0x00000100  # Extended rights
ADS_RIGHT_DS_CREATE_CHILD = 0x00000001    # Create child objects
ADS_RIGHT_DS_DELETE_CHILD = 0x00000002    # Delete child objects  
ADS_RIGHT_DS_READ_PROP = 0x00000010       # Read property
ADS_RIGHT_DS_WRITE_PROP = 0x00000020      # Write property
ADS_RIGHT_DS_SELF = 0x00000008            # Self modification

ACCESS_DENIED_ACE

Denies access rights to a trustee.
# ACE Type: 0x01
# Structure identical to ACCESS_ALLOWED_ACE

ACCESS_DENIED_OBJECT_ACE

Object-specific access denial.
# ACE Type: 0x06  
# Structure identical to ACCESS_ALLOWED_OBJECT_ACE

Access Masks

ACCESS_MASK

Represents access rights in an ACE.
from impacket.ldap.ldaptypes import ACCESS_MASK

mask = ACCESS_MASK()
mask['Mask'] = 0x001f01ff

if mask.hasPriv(ACCESS_MASK.GENERIC_ALL):
    print("Has full control")

Standard Rights

GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000

DELETE = 0x00010000
READ_CONTROL = 0x00020000
WRITE_DACL = 0x00040000
WRITE_OWNER = 0x00080000

Methods

hasPriv(priv) Check if a specific privilege is set.
if mask.hasPriv(ACCESS_MASK.WRITE_DACL):
    print("Can modify DACL")
setPriv(priv) Set a specific privilege.
mask.setPriv(ACCESS_MASK.READ_CONTROL)
removePriv(priv) Remove a specific privilege.
mask.removePriv(ACCESS_MASK.WRITE_OWNER)

Security Descriptor Flags

LDAP_SERVER_SD_FLAGS

Control which parts of the security descriptor to retrieve.
from impacket.ldap.ldaptypes import LDAP_SERVER_SD_FLAGS
from impacket.ldap.ldapasn1 import Control

# Request only DACL
sd_flags_control = Control()
sd_flags_control['controlType'] = '1.2.840.113556.1.4.801'
sd_flags_control['controlValue'] = struct.pack('<I', 
    LDAP_SERVER_SD_FLAGS.OWNER_SECURITY_INFORMATION.value |
    LDAP_SERVER_SD_FLAGS.DACL_SECURITY_INFORMATION.value
)

results = conn.search(
    searchFilter='(sAMAccountName=user)',
    attributes=['nTSecurityDescriptor'],
    searchControls=[sd_flags_control]
)

Flags

  • OWNER_SECURITY_INFORMATION (0x1): Owner SID
  • GROUP_SECURITY_INFORMATION (0x2): Group SID
  • DACL_SECURITY_INFORMATION (0x4): DACL
  • SACL_SECURITY_INFORMATION (0x8): SACL

Object Type GUIDs

OBJECTTYPE_GUID_MAP

Common object class GUIDs for Active Directory.
from impacket.ldap.ldaptypes import OBJECTTYPE_GUID_MAP

user_guid = OBJECTTYPE_GUID_MAP[b'user']
# 'bf967aba-0de6-11d0-a285-00aa003049e2'

group_guid = OBJECTTYPE_GUID_MAP[b'group']  
# 'bf967a9c-0de6-11d0-a285-00aa003049e2'

Complete Example

from impacket.ldap import ldap
from impacket.ldap.ldaptypes import (
    SR_SECURITY_DESCRIPTOR, ACE, ACCESS_ALLOWED_OBJECT_ACE
)

# Connect and authenticate
conn = ldap.LDAPConnection('ldap://dc.example.com')
conn.login('admin', 'password', 'EXAMPLE')

# Query security descriptor
results = conn.search(
    searchFilter='(sAMAccountName=testuser)',
    attributes=['nTSecurityDescriptor']
)

for entry in results:
    if not entry.get('objectName'):
        continue
        
    for attr in entry['attributes']:
        if str(attr['type']) == 'nTSecurityDescriptor':
            sd_data = bytes(attr['vals'][0])
            sd = SR_SECURITY_DESCRIPTOR(data=sd_data)
            
            print(f"Owner: {sd['OwnerSid'].formatCanonical()}")
            
            # Parse DACL
            dacl = sd['Dacl']
            print(f"DACL has {dacl['AceCount']} ACEs")
            
            for ace in dacl.aces:
                ace_info = ace['Ace']
                print(f"  Type: {ace['TypeName']}")
                print(f"  SID: {ace_info['Sid'].formatCanonical()}")
                print(f"  Mask: 0x{ace_info['Mask']['Mask']:08x}")
                
                # Check for object ACEs
                if ace['AceType'] == ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE:
                    if ace_info.hasFlag(ACCESS_ALLOWED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT):
                        print(f"  Object GUID: {ace_info['ObjectType'].hex()}")

conn.close()