{"id":"PYSEC-2026-2590","summary":"Lemur: LDAP Authentication Globally Disables TLS Certificate Verification When LDAP_USE_TLS Is Enabled","details":"## Description\n\n### Overview\n\nWhen LDAP TLS is enabled (`LDAP_USE_TLS = True`), Lemur's LDAP authentication module unconditionally disables TLS certificate verification at the **global** `ldap` module level. This allows a man-in-the-middle attacker positioned between Lemur and the LDAP server to intercept all authentication credentials.\n\n### Vulnerable Code\n\n**Location:** `lemur/auth/ldap.py`, `_bind()` method, line ~172\n\n```python\nif self.ldap_use_tls:\n    ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)\n```\n\nKey issues:\n\n1. `ldap.set_option()` is a **global** call (as opposed to `self.ldap_client.set_option()`), meaning it disables TLS verification for the entire Python process, not just this connection\n2. `OPT_X_TLS_NEVER` means no certificate validation is performed whatsoever — self-signed, expired, wrong hostname, and revoked certificates are all silently accepted\n3. There is no configuration option to override this behavior — TLS verification is always disabled when TLS is enabled\n\n### Impact\n\nA network-positioned attacker (man-in-the-middle) between Lemur and the LDAP server can:\n\n- **Intercept all LDAP credentials** (usernames and plaintext passwords) for every user who authenticates\n- **Modify LDAP responses** to inject arbitrary group memberships, granting admin access\n- **Compromise the entire PKI infrastructure** managed by Lemur, since authentication controls access to certificates and private keys\n\nThis is particularly severe because Lemur is a certificate management system — the tool designed to manage TLS security is itself vulnerable to a TLS attack.\n\n### Steps to Reproduce\n\n1. Deploy Lemur with LDAP TLS enabled:\n   ```python\n   LDAP_AUTH = True\n   LDAP_USE_TLS = True\n   LDAP_BIND_URI = \"ldaps://dc.corp.example.com\"\n   ```\n\n2. Intercept the LDAP connection using a TLS proxy (e.g., `mitmproxy` or `stunnel`):\n   ```bash\n   # Generate a self-signed certificate\n   openssl req -x509 -newkey rsa:2048 -keyout mitm.key -out mitm.crt -days 1 -nodes -subj \"/CN=mitm\"\n\n   # Proxy LDAP traffic\n   stunnel -d 0.0.0.0:636 -r real-ldap-server:636 -p mitm.pem\n   ```\n\n3. Point Lemur's `LDAP_BIND_URI` at the proxy (or perform ARP spoofing/DNS hijacking)\n\n4. Observe that Lemur connects without any certificate verification error\n\n5. All credentials are visible in the proxy's TLS session\n\n### Remediation\n\nRemove the global TLS verification bypass and default to strict verification:\n\n```python\nif self.ldap_use_tls:\n    # Use instance-level option, not global\n    self.ldap_client.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)\n    self.ldap_client.set_option(ldap.OPT_PROTOCOL_VERSION, 3)\n    if self.ldap_cacert_file:\n        self.ldap_client.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ldap_cacert_file)\n```\n\nIf backward compatibility is needed, make it configurable with a secure default:\n\n```python\ntls_require_cert = current_app.config.get(\"LDAP_TLS_REQUIRE_CERT\", ldap.OPT_X_TLS_DEMAND)\nself.ldap_client.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_require_cert)\n```\n\n### Resources\n\n- CWE-295: https://cwe.mitre.org/data/definitions/295.html\n- python-ldap TLS documentation: https://www.python-ldap.org/en/python-ldap-3.4.0/reference/ldap.html#tls-options","aliases":["CVE-2026-44305","GHSA-vr7c-r5gj-j3w5"],"modified":"2026-07-13T16:32:03.203707167Z","published":"2026-07-13T15:15:39.032789Z","references":[{"type":"WEB","url":"https://github.com/Netflix/lemur/security/advisories/GHSA-vr7c-r5gj-j3w5"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44305"},{"type":"PACKAGE","url":"https://github.com/Netflix/lemur"},{"type":"WEB","url":"https://github.com/Netflix/lemur/releases/tag/v1.9.0"},{"type":"WEB","url":"https://www.python-ldap.org/en/python-ldap-3.4.0/reference/ldap.html#tls-options"},{"type":"PACKAGE","url":"https://pypi.org/project/lemur"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-vr7c-r5gj-j3w5"}],"affected":[{"package":{"name":"lemur","ecosystem":"PyPI","purl":"pkg:pypi/lemur"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.9.0"}]}],"versions":["0.11.0","0.2.1","0.8.0","0.8.1","0.9.0","1.0.0","1.1.0","1.2.0","1.3.1","1.3.2","1.4.0","1.5.0","1.6.0","1.7.0","1.8.0","1.8.1","1.8.2"],"database_specific":{"source":"https://github.com/pypa/advisory-database/blob/main/vulns/lemur/PYSEC-2026-2590.yaml"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N"}]}