NetExec not detecting Linux LDAP Servers (or LDAP servers without SMB/Samba enabled).
Describe the bug Linux LDAP servers go undetected with a NetExec LDAP scan when there is no SMB/Samba server running on the host. I recently set up an LDAP anonymous bind server to test out something I'm working on and when I run NetExec, either in scan mode or by directly targeting the LDAP server IP address, it returns no results. See the following:
To Reproduce
Steps to reproduce the behavior i.e.:
Command(s):
netexec ldap linux_ldap_server_ip_or_hostname --no-smb # this is what triggers the stack trace
netexec ldap linux_ldap_server_ip_or_hostname # this doesn't trigger an error but it doesn't identify the LDAP server either
Resulted in:
[14:13:27] ERROR Exception while calling proto_flow() on target 192.168.30.15: 'NoneType' object has no attribute 'split'
connection.py:168
Traceback (most recent call last):
/root/.local/pipx/venvs/netexec/lib/python3.10/site-packages/nxc/connection.py:163 in __init__
160 self.logger.info(f"Socket info: host={self.host}, hostname={self.hostname}, kerberos={self.kerberos}, ipv6={self.is_ipv6}, link-local ipv6={self.is_link_local_ipv6}")
161
162 try:
163 self.proto_flow()
164 except Exception as e:
165 if "ERROR_DEPENDENT_SERVICES_RUNNING" in str(e):
166 self.logger.error(f"Exception while calling proto_flow() on target {target}: {e}")
/root/.local/pipx/venvs/netexec/lib/python3.10/site-packages/nxc/connection.py:223 in proto_flow
220 else:
221 self.logger.debug("Created connection object")
222 self.enum_host_info()
223 if self.print_host_info() and (self.login() or (self.username == "" and self.password == "")):
224 if hasattr(self.args, "module") and self.args.module:
225 self.load_modules()
226 self.logger.debug("Calling modules")
/root/.local/pipx/venvs/netexec/lib/python3.10/site-packages/nxc/protocols/ldap.py:307 in print_host_info
304 if self.args.no_smb:
305 self.logger.extra["protocol"] = "LDAP" if self.port == "389" else "LDAPS"
306 self.logger.extra["port"] = self.port
307 self.logger.display(f'{self.baseDN} (Hostname: {self.hostname.split(".")[0]}) (domain: {self.domain})')
308 else:
309 self.logger.extra["protocol"] = "SMB" if not self.no_ntlm else "LDAP"
310 self.logger.extra["port"] = "445" if not self.no_ntlm else "389"
Expected behavior The LDAP server should be identified by NetExec with or without the --no-smb flag (but especially with the --no-smb flag).
NetExec info
- OS:
root@redacted:/opt# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy
root@redacted:/opt# uname -a
Linux vpentest 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:28:59 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
- Version of nxc:
1.2.0 - ItsAlwaysDNS - e927f33 - Installed from: pipx
Screenshots
Without the --no-smb-flag:
When I add in the --no-smb flag, I get the following error:
Potential Remediation Idea
LDAP servers will (as far as I know) always allow you to bind to them in order to get the Directory Service Entry (The DSE includes the domain name and naming contexts along with some other details. nmap does this when scanning with the -sC or -A flags). This bind does not require any credentials. See example below:
>>> from ldap3 import *
>>> srv = Server("192.168.30.15", get_info=ALL, port=389, use_ssl=False)
>>> conn = Connection(srv)
>>> conn.bind()
True
>>> srv.info
DSA info (from DSE):
Supported LDAP versions: 3
Naming contexts:
ou=system
ou=schema
dc=example,dc=com
<snipped for brevity>
This is a way you could check if an LDAP server is available without requiring any SMB interaction and would, more specifically, be much more reliable, especially on Linux-based LDAP platforms (OpenLDAP, ApacheDS, etc...).
Thoughts? Let me know if you need more input and thank you!
Thanks for the report!
Imo NetExec is not designed to "scan" for targets. It rather should be used to exploit/use enumerated targets. Therefore, i think "not detecting" an edge case or unusual setup is not a fault of the tool itself, as we need SMB for enumerating the targets OS/hostname/domain. This should be done with nmap or something similar.
The crash with --no-smb is definitely a bug though! As you are not using a Domain Controller you probably also don't have ntlm available?
Still, in a normal AD environment it looks like it is still working:
Can you provide the debug log for further debugging?
This was fixed by #508