1

I am trying to create a service account via the Ldap3 library in Python. The service account is successfully created, but there is a small problem. The "User cannot change password" checkboxes is not selected.

I did some research and found that to set this property I need to follow some steps given here : https://learn.microsoft.com/en-us/windows/win32/adsi/modifying-user-cannot-change - password-ldap-provider . The logic given in this link is in a different programming language than Python, so i tried to replicate the same logic in Python. From what we understand, I’ve implemented the feature, which executed successfully, but didn't see the expected effect on the AD server ("User cannot change password" checkbox is still unchecked).

Below is the code used to create and add the ACL object to the service account.

def create_object_ace(privguid, sid):
    print("creating ace object")
    nace = ldaptypes.ACE()
    nace['AceType'] =     ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_DENIED_OBJECT_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CONTROL_ACCESS
acedata['ObjectType'] = string_to_bin(privguid)
acedata['InheritedObjectType'] = b''
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
assert sid == acedata['Sid'].formatCanonical()
acedata['Flags'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT
nace['Ace'] = acedata
return nace

s = Server('ad_server.com', get_info=ALL)
c = Connection(s, user="testdomain\\username", password="password", authentication=NTLM)
 c.search(search_base="DC=testad,DC=com", search_filter="(CN=svc_account_47)",
     search_scope=SUBTREE, attributes=['objectSid', 'sAMAccountName'])

entry = c.entries[0]
usersid = entry['objectSid'].value

controls = security_descriptor_control(sdflags=0x04)
 c.search(search_base="DC=testahs,DC=com", search_filter='(&(objectCategory=domain))',
     attributes=['SAMAccountName', 'nTSecurityDescriptor'], controls=controls)
entry = c.entries[0]
secDescData =.    entry['nTSecurityDescriptor'].raw_values[0]
secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR(data=secDescData)

secDesc['Dacl']['Data'].append(create_object_ace('ab721a53-1e2f-11d0-9819-00aa0040529b', usersid)) # This GUID is for 'User cannot change password'

dn = entry.entry_dn
data = secDesc.getData()

c.modify(dn, {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [data])}, controls=controls)

print(c.result)  

# gives -> {'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'modifyResponse'}

The Python code reference is from the following link:

https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/ntlmrelayx/attacks/ldapattack.py

Can someone help me here. Thanks in advance.

  • entry = c.entries[0] usersid = entry['objectSid'].value That doesnt parse the value – user2273231 Jul 29 '22 at 13:00
  • AFTER fixing the SID, i now get the following error entry = c.entries[0] usersid = entry['objectSid'].value That doesnt parse the value, after i managed to get the SID i now face the followingf probkem: creating ace object Traceback (most recent call last): File "C:\problem2.py", line 103, in secDesc['Dacl']['Data'].append(create_object_ace('ab721a53-1e2f-11d0-9819-00aa0040529b', usersid)) # This GUID is for 'User cannot change password' File "C:\problem2.py", line 80, in create_object_ace acedata['Sid'].fromCanonical(sid) – user2273231 Jul 29 '22 at 13:18
  • items = canonical.split('-') AttributeError: 'Attribute' object has no attribute 'split' – user2273231 Jul 29 '22 at 13:26
  • Okay, so found the sid wasn’t being set as a string but a byte object, however even know it says success it still fails to apply the checkbox – user2273231 Jul 29 '22 at 23:30

0 Answers0