Addressing Security Weaknesses in the NGINX LDAP Reference Implementation

Original: https://www.nginx.com/blog/addressing-security-weaknesses-nginx-ldap-reference-implementation/

On 9 April 2022, security vulnerabilities in the NGINX LDAP reference implementation were publicly shared. We have determined that only the reference implementation is affected. NGINX Open Source and NGINX Plus are not themselves affected, and no corrective action is necessary if you do not use the reference implementation.

The NGINX LDAP reference implementation uses LDAP to authenticate users of applications being proxied by NGINX. It is published as a Python daemon and related NGINX configuration at https://github.com/nginxinc/nginx-ldap-auth, and its purpose and configuration are described in detail on our blog.

Deployments of the LDAP reference implementation are affected by the vulnerabilities if any of the following conditions apply. Below we further discuss the conditions and how to mitigate them:

  1. Command-line parameters are used to configure the Python daemon
  2. There are unused, optional configuration parameters
  3. LDAP authentication depends on specific group membership

Note: The LDAP reference implementation is published as a reference implementation and describes the mechanics of how the integration works and all of the components required to verify the integration. It is not a production‑grade LDAP solution. For example, there is no encryption of the username and password used for the sample login page, and security notices call this out.

Mitigating Condition 1: Command-Line Parameters Are Used to Configure the Python Daemon

The primary way to configure the LDAP reference implementation is with a number of proxy_set_header directives as detailed in the sample configuration and the documentation. However, the configuration parameters can also be set on the command line that initializes the Python daemon (nginx-ldap-auth-daemon.py).

When configuration parameters are specified on the command line, an attacker can override some or all of them by passing specially crafted HTTP request headers. To protect against this, ensure that the corresponding configuration parameters have an empty value in the location = /auth-proxy block in the NGINX configuration (nginx-ldap-auth.conf in the repo).

location = /auth-proxy {
    ...
    proxy_set_header X-Ldap-URL      ""; # Empty value when using command-line 
                                         # config
    proxy_set_header X-Ldap-BaseDN   ""; # Empty value when using command-line
                                         # config
    proxy_set_header X-Ldap-BindDN   ""; # Empty value when using command-line
                                         # config
    proxy_set_header X-Ldap-BindPass ""; # Empty value when using command-line
                                         # config
    ...
}

Mitigating Condition 2: Unused, Optional Configuration Parameters

As in Condition 1, an attacker can pass specially crafted HTTP request headers to override certain configuration parameters, depending on the configuration used for the LDAP search template. To protect against this, ensure that any unused, optional parameters have an empty value in the location = /auth-proxy block in the NGINX configuration.

location = /auth-proxy {
    ...
    proxy_set_header X-Ldap-Template ""; # Optional, but do not comment 
                                         # (use empty value)
    proxy_set_header X-CookieName    ""; # Optional, but do not comment
                                         # (use empty value)
    proxy_set_header X-Ldap-Realm    ""; # Optional, but do not comment
                                         # (use empty value)
    proxy_set_header X-Ldap-Starttls ""; # "True" or empty (do not comment)
    ...
}

Mitigating Condition 3: LDAP Group Membership Is Required

The Python daemon does not sanitize its inputs. Consequently, an attacker can use a specially crafted request header to bypass the group membership (memberOf) check and so force LDAP authentication to succeed even if the user being authenticated does not belong to the required groups.

To mitigate against this, ensure that the backend daemon that presents the login form strips any special characters from the username field. In particular, it must remove the opening and closing parenthesis characters – ( ) – and the equal sign (=), which all have special meaning for LDAP servers. The backend daemon in the LDAP reference implementation will be updated in this way in due course.

Acknowledgements

We thank valodzka and @_Blue_hornet for highlighting these security vulnerabilities.

Retrieved by Nick Shadrin from nginx.com website.