HIGH ldap injectionexpressapi keys

Ldap Injection in Express with Api Keys

Ldap Injection in Express with Api Keys — how this specific combination creates or exposes the vulnerability

Ldap Injection occurs when an attacker is able to manipulate LDAP query construction, typically by injecting malicious filter fragments. In Express applications that rely on Api Keys for access control, this risk pattern can emerge when the API key is used to select or scope LDAP searches without proper sanitization. For example, an Api Key may be mapped to an organizational unit (OU) or group membership, and that mapping is directly concatenated into an LDAP filter. If the key or any user-controlled value derived from it is not strictly validated and escaped, an attacker can supply crafted input that alters the filter logic.

Consider an endpoint that accepts a username and uses the Api Key to determine which branch of the directory to search:

const ldap = require('ldapjs');
const client = ldap.createClient({ url: 'ldap://dc.example.com' });

app.get('/users', (req, res) => {
  const apiKey = req.header('x-api-key');
  const username = req.query.username || '';
  const base = 'ou=' + apiKey + ',dc=example,dc=com';
  const filter = '(uid=' + username + ')';

  client.search(base, { filter: filter }, (err, search) => {
    // handle results
  });
});

In this pattern, both apiKey and username are concatenated directly into the base DN and filter. If the Api Key contains characters such as parentheses, asterisks, or backslashes, or if the username input is not escaped, the intended scope and filter can be overwritten. An attacker could supply username=*)(objectClass=*) to return all objects in the subtree, or manipulate the base DN to point to an external directory. Because the scan category BOLA/IDOR and Property Authorization are part of the 12 parallel checks, such expressions involving identity-based access and authorization logic are flagged when directory inputs are not rigorously validated.

Moreover, if the Api Key itself is leaked through logs, error messages, or client-side storage, the attacker gains not only a lookup scope but also potential insight into the directory hierarchy. This combines the weaknesses of weak access scoping (BOLA) and insecure data exposure. The LDAP filter is not a structured query language, so escaping must be applied to special characters according to RFC 4515. Without this, even well-intentioned use of Api Keys to partition data can become a pivot point for information disclosure or unauthorized traversal, which would be surfaced in the scan’s Inventory Management and Data Output findings.

Api Keys-Specific Remediation in Express — concrete code fixes

Remediation focuses on strict input validation, canonicalization, and using an LDAP library that supports safe filter construction rather than string concatenation. Api Keys should be treated as opaque tokens; their structure should not dictate directory paths unless those paths are pre-mapped server-side with strict allowlists. Never build base DNs or filters by concatenating raw key or user input.

First, validate the Api Key against a known set or pattern before using it to derive any directory information. If keys represent tenants or OUs, map them server-side to a canonical DN using a lookup table:

const VALID_TENANTS = new Map([
  ['key-a1b2', 'ou=tenantA,dc=example,dc=com'],
  ['key-x9y8', 'ou=tenantB,dc=example,dc=com']
]);

function getBaseFromKey(apiKey) {
  return VALID_TENANTS.get(apiKey);
}

Second, use an LDAP library that provides filter escaping. For example, ldapjs does not automatically escape filter components, so you must apply escaping manually or choose a wrapper that does. Use a function to escape special characters according to RFC 4515:

function escapeLdapFilter(input) {
  if (typeof input !== 'string') return '';
  return input.replace(/([*()\\])/g, '\\$1');
}

Then construct the filter safely:

app.get('/users', (req, res) => {
  const apiKey = req.header('x-api-key');
  const username = req.query.username || '';

  const base = getBaseFromKey(apiKey);
  if (!base) {
    return res.status(401).send('Invalid API key');
  }

  const safeUsername = escapeLdapFilter(username);
  const filter = `(uid=${safeUsername})`;

  client.search(base, { filter: filter }, (err, search) => {
    if (err) return res.status(500).send('Directory error');
    // collect and return results
  });
});

Additionally, enforce length and character restrictions on usernames, prefer parameterized searches, and avoid returning verbose error details that could aid injection. By treating the Api Key as an authentication token rather than a directory path component, and by canonicalizing and escaping all user-supplied input, the application mitigates Ldap Injection while preserving the intended access scoping. These practices align with the remediation guidance provided in the scan findings for BOLA/IDOR and Property Authorization checks.

Frequently Asked Questions

Can Ldap Injection occur if the Api Key is validated but the username is not escaped?
Yes. Even with a valid Api Key, failing to escape the username allows an attacker to terminate or alter the LDAP filter, potentially exposing unintended directory entries or bypassing intended access controls.
Is simply hashing or encrypting the Api Key enough to prevent Ldap Injection?
No. Hashing or encrypting the key does not prevent injection if the application still uses untrusted input to build LDAP filters or base DNs. Input validation and filter escaping remain essential regardless of how the key is stored.