Skip to content

Commit 416affa

Browse files
author
SkelSec
committed
helping signing scanners, adding timeout
1 parent bb3691e commit 416affa

File tree

5 files changed

+58
-6
lines changed

5 files changed

+58
-6
lines changed

msldap/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
__version__ = "0.5.9"
2+
__version__ = "0.5.10"
33
__banner__ = \
44
"""
55
# msldap %s

msldap/client.py

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def __init__(self, target:MSLDAPTarget, creds:UniCredential, connection = None,
5151
self.target = target
5252
self.keepalive = keepalive
5353
self.ldap_query_page_size = 1000
54+
self._disable_channel_binding = False
55+
self._disable_signing = False
56+
self._null_channel_binding = False
5457
if self.target is not None:
5558
self.ldap_query_page_size = self.target.ldap_query_page_size
5659

@@ -109,6 +112,9 @@ async def connect(self):
109112
self.disconnected_evt = asyncio.Event()
110113
if self._con is None:
111114
self._con = MSLDAPClientConnection(self.target, self.creds)
115+
self._con._disable_channel_binding = self._disable_channel_binding
116+
self._con._disable_signing = self._disable_signing
117+
self._con._null_channel_binding = self._null_channel_binding
112118
_, err = await self._con.connect()
113119
if err is not None:
114120
raise err

msldap/connection.py

+21-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def __init__(self, target:MSLDAPTarget, credential:UniCredential, auth=None):
4949
self.message_table_notify = {}
5050
self.encryption_sequence_counter = 0 # this will be set by the inderlying auth algo
5151
self.cb_data = None #for channel binding
52+
self._disable_channel_binding = False # putting it here for scanners to be able to turn it off
53+
self._disable_signing = False
54+
self._null_channel_binding = False
5255

5356
if self.credential.protocol == asyauthProtocol.NONE:
5457
self.is_anon = True
@@ -187,12 +190,15 @@ async def connect(self):
187190
self.connection_closed_evt = asyncio.Event()
188191
packetizer = LDAPPacketizer()
189192
client = UniClient(self.target, packetizer)
190-
self.network = await client.connect()
193+
self.network = await asyncio.wait_for(client.connect(), timeout=self.target.timeout)
191194

192195
# now processing channel binding options
193-
if self.target.protocol == UniProto.CLIENT_SSL_TCP:
194-
certdata = self.network.get_peer_certificate()
195-
self.cb_data = b'tls-server-end-point:' + sha256(certdata).digest()
196+
if self.target.protocol == UniProto.CLIENT_SSL_TCP and self._disable_channel_binding is False:
197+
if self._null_channel_binding is True:
198+
self.cb_data = b'tls-server-end-point:' + sha256(b'').digest()
199+
else:
200+
certdata = self.network.get_peer_certificate()
201+
self.cb_data = b'tls-server-end-point:' + sha256(certdata).digest()
196202

197203
self.handle_incoming_task = asyncio.create_task(self.__handle_incoming())
198204
self.status = MSLDAPClientStatus.CONNECTED
@@ -250,6 +256,12 @@ async def bind(self):
250256
flags = ISC_REQ.CONNECTION|ISC_REQ.CONFIDENTIALITY|ISC_REQ.INTEGRITY
251257
if self.target.protocol == UniProto.CLIENT_SSL_TCP:
252258
flags = ISC_REQ.CONNECTION
259+
260+
# this switch is for the case when we are using NTLM and we want to disable signing
261+
# useful for testing if the server supports it
262+
if self._disable_signing is True:
263+
flags = ISC_REQ.CONNECTION
264+
253265
data, to_continue, err = await self.auth.authenticate(None, spn=self.target.to_target_string(), flags=flags, cb_data = self.cb_data)
254266
if err is not None:
255267
return None, err
@@ -385,6 +397,11 @@ async def bind(self):
385397
if self.target.protocol == UniProto.CLIENT_SSL_TCP:
386398
flags = ISC_REQ.CONNECTION
387399

400+
# this switch is for the case when we are using NTLM and we want to disable signing
401+
# useful for testing if the server supports it
402+
if self.credential.protocol == asyauthProtocol.NTLM and self._disable_signing is True:
403+
flags = ISC_REQ.CONNECTION
404+
388405
data, to_continue, err = await self.auth.authenticate(challenge, cb_data = self.cb_data, spn=self.target.to_target_string(), flags=flags)
389406
if err is not None:
390407
raise err

msldap/examples/msldapclient.py

+23
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ def __init__(self, url = None):
5656
self.adinfo = None
5757
self.ldapinfo = None
5858
self.domain_name = None
59+
self.noisig = False
60+
self.nocb = False
61+
self._disable_channel_binding = False
62+
self._disable_signing = False
63+
self._null_channel_binding = False
5964
self.__current_dirs = {}
6065
self._current_dn = None
6166

@@ -73,6 +78,9 @@ async def do_login(self, url = None):
7378

7479
self.connection = self.conn_url.get_client()
7580
self.connection.keepalive = True
81+
self.connection._disable_channel_binding = self._disable_channel_binding
82+
self.connection._disable_signing = self._disable_signing
83+
self.connection._null_channel_binding = self._null_channel_binding
7684
_, err = await self.connection.connect()
7785
if err is not None:
7886
raise err
@@ -88,6 +96,21 @@ async def do_login(self, url = None):
8896
except:
8997
traceback.print_exc()
9098
return False
99+
100+
async def do_nosig(self):
101+
"""Disables signing"""
102+
self._disable_signing = True
103+
return True
104+
105+
async def do_nocb(self):
106+
"""Disables channel binding"""
107+
self._disable_channel_binding = True
108+
return True
109+
110+
async def do_nullcb(self):
111+
"""Sets incorrect channel binding data"""
112+
self._null_channel_binding = True
113+
return True
91114

92115
async def do_ldapinfo(self, show = True):
93116
"""Prints detailed LDAP connection info (DSA)"""

msldap/ldap_objects/adinfo.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
'objectGUID', 'objectSid', 'pwdHistoryLength',
1616
'pwdProperties', 'serverState', 'systemFlags', 'uASCompat', 'uSNChanged',
1717
'uSNCreated', 'whenChanged', 'whenCreated', 'rIDManagerReference',
18-
'msDS-Behavior-Version', 'description', 'isDeleted', 'gPLink'
18+
'msDS-Behavior-Version', 'description', 'isDeleted', 'gPLink', 'ms-DS-MachineAccountQuota'
1919
]
2020

2121
class MSADInfo:
@@ -54,6 +54,7 @@ def __init__(self):
5454
self.description = None
5555
self.isDeleted = None
5656
self.gPLink = None
57+
self.machineAccountQuota = None
5758

5859
@staticmethod
5960
def from_ldap(entry):
@@ -91,6 +92,7 @@ def from_ldap(entry):
9192
adi.description = entry['attributes'].get('description')
9293
adi.isDeleted = entry['attributes'].get('isDeleted')
9394
adi.gPLink = entry['attributes'].get('gPLink')
95+
adi.machineAccountQuota = entry['attributes'].get('ms-DS-MachineAccountQuota')
9496

9597
#https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/564dc969-6db3-49b3-891a-f2f8d0a68a7f
9698
adi.domainmodelevel = entry['attributes'].get('msDS-Behavior-Version')
@@ -130,6 +132,7 @@ def to_dict(self):
130132
d['whenCreated'] = self.whenCreated
131133
d['domainmodelevel'] = self.domainmodelevel
132134
d['description'] = self.description
135+
d['ms-DS-MachineAccountQuota'] = self.machineAccountQuota
133136
return d
134137

135138

@@ -166,6 +169,9 @@ def __str__(self):
166169
t += 'whenCreated: %s\n' % self.whenCreated
167170
t += 'domainmodelevel: %s\n' % self.domainmodelevel
168171
t += 'description: %s\n' % self.description
172+
t += 'isDeleted: %s\n' % self.isDeleted
173+
t += 'gPLink: %s\n' % self.gPLink
174+
t += 'ms-DS-MachineAccountQuota: %s\n' % self.machineAccountQuota
169175
return t
170176

171177
def get_row(self, attrs):

0 commit comments

Comments
 (0)