| パッケージ | 影響を受けるバージョン | 修正済みバージョン |
|---|---|---|
| lemur | < 1.9.0 | 1.9.0 |
When 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.
Location: lemur/auth/ldap.py, _bind() method, line ~172
if self.ldap_use_tls:
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
Key issues:
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 connectionOPT_X_TLS_NEVER means no certificate validation is performed whatsoever — self-signed, expired, wrong hostname, and revoked certificates are all silently acceptedA network-positioned attacker (man-in-the-middle) between Lemur and the LDAP server can:
This is particularly severe because Lemur is a certificate management system — the tool designed to manage TLS security is itself vulnerable to a TLS attack.
Deploy Lemur with LDAP TLS enabled:
LDAP_AUTH = True
LDAP_USE_TLS = True
LDAP_BIND_URI = "ldaps://dc.corp.example.com"
Intercept the LDAP connection using a TLS proxy (e.g., mitmproxy or stunnel):
# Generate a self-signed certificate
openssl req -x509 -newkey rsa:2048 -keyout mitm.key -out mitm.crt -days 1 -nodes -subj "/CN=mitm"
# Proxy LDAP traffic
stunnel -d 0.0.0.0:636 -r real-ldap-server:636 -p mitm.pem
Point Lemur's LDAP_BIND_URI at the proxy (or perform ARP spoofing/DNS hijacking)
これらの製品をお使いですか?サイトをスキャンして、脆弱なバージョンが公開されていないか確認しましょう。
無料でサイトをスキャンObserve that Lemur connects without any certificate verification error
All credentials are visible in the proxy's TLS session
Remove the global TLS verification bypass and default to strict verification:
if self.ldap_use_tls:
# Use instance-level option, not global
self.ldap_client.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
self.ldap_client.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
if self.ldap_cacert_file:
self.ldap_client.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ldap_cacert_file)
If backward compatibility is needed, make it configurable with a secure default:
tls_require_cert = current_app.config.get("LDAP_TLS_REQUIRE_CERT", ldap.OPT_X_TLS_DEMAND)
self.ldap_client.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_require_cert)