Ldap Injection in Adonisjs with Cockroachdb
Ldap Injection in Adonisjs with Cockroachdb — how this specific combination creates or exposes the vulnerability
LDAP injection occurs when an attacker can manipulate LDAP query construction, typically through unsanitized user input used in filter strings. In an AdonisJS application that delegates authentication or user search to an LDAP directory backed by CockroachDB as a persistent store, this risk surfaces in two distinct layers: the LDAP filter construction in NodeJS code and the relational data handling in CockroachDB.
AdonisJS does not provide built-in LDAP escaping helpers, so developers often construct filters using string concatenation or template literals. For example, a login route might build an LDAP filter like (&(uid=${username})(userPassword=${password})). If username is supplied directly from an HTTP request, an attacker can inject LDAP metacharacters such as *, (, ), or | to alter the filter logic. A payload like admin)(uid=* can change the filter to (&(uid=admin)(uid=*)(userPassword=...)), potentially bypassing authentication by matching unintended entries.
CockroachDB becomes relevant when the application stores or indexes LDAP-related metadata (e.g., mapped user IDs, group memberships, or sync state). If the application builds SQL queries by interpolating LDAP-derived values without parameterization, attackers can exploit SQL injection to read or modify this metadata, escalating the impact. A typical vulnerable AdonisJS ORM query might look like UserMeta.query().where('ldap_dn', username).first() if username is sourced from LDAP input. An attacker could supply ' OR 1=1 -- as the username, causing the query to return sensitive mappings or enabling further attacks.
The combination is risky because LDAP filters and SQL queries are both string-based constructs. An AdonisJS service that synchronizes LDAP groups into CockroachDB might use code such as:
const ldapFilter = `(memberOf=cn=${groupName},ou=groups,dc=example,dc=com)`;
const users = await ldapClient.search({ filter: ldapFilter });
// Later, syncing to CockroachDB without sanitization
await Database.from('ldap_mappings').insert({ groupName, users: users.map(u => u.uid) });
If groupName originates from an unvalidated parameter, LDAP injection can modify the search base or filter, and the subsequent insert into CockroachDB may store attacker-influenced mappings. This can lead to privilege escalation or data exposure when the application later uses these mappings for authorization checks.
Because middleBrick tests unauthenticated attack surfaces and supports OpenAPI/Swagger analysis, it can surface endpoints that accept user-supplied values used in LDAP filter construction or in SQL statements affecting LDAP-related metadata. The scanner’s checks include Input Validation and Property Authorization, which can highlight missing validation on parameters involved in LDAP operations. Findings will reference relevant attack patterns such as LDAP injection and mapping to frameworks like OWASP API Top 10.
Cockroachdb-Specific Remediation in Adonisjs — concrete code fixes
Remediation focuses on strict separation of LDAP filter construction and SQL parameterization, along with input validation and output encoding. Do not concatenate user input into LDAP filters. Instead, use a dedicated LDAP escaping function or library. For SQL interactions with CockroachDB via AdonisJS, always use parameterized queries or the query builder with bound values.
1. Secure LDAP filter construction
Use an LDAP filter escaper to escape special characters in attributes used in filters. For example, define a helper that escapes characters defined in RFC 4515:
function escapeLDAPFilter(value) {
// Basic escape mapping per RFC 4515
return String(value)
.replace(/\\/g, '\\\\')
.replace(/\*/g, '\\2a')
.replace(/\(/g, '\\28')
.replace(/\)/g, '\\29')
.replace(/\x00/g, '\\00')
.replace(/\\/g, '\\\\')
.replace(/'/g, '\\27')
.replace(/=/g, '\\3d')
.replace(/</g, '\\3c')
.replace(/>/g, '\\3e')
.replace(/;/g, '\\3b')
.replace(/,/g, '\\2c');
}
const safeUsername = escapeLDAPFilter(username);
const ldapFilter = `(&(uid=${safeUsername})(userPassword=__PASSWORD_PLACEHOLDER__))`;
// Use with an LDAP client that does not further interpret the filter string as code
Prefer using a well-maintained library for escaping if available, and avoid building filters via template literals with raw input.
2. Parameterized SQL for CockroachDB
When storing or querying LDAP-related metadata in CockroachDB, use AdonisJS’s query builder with bound parameters. For example:
// ✅ Safe: parameterized query
const mapping = await Database.from('ldap_mappings')
.where('ldap_dn', username) // username is passed as a parameter, not interpolated
.first();
// ✅ Safe: parameterized insert
await Database.table('ldap_mappings').insert({
ldap_dn: username,
group_name: groupName,
synced_at: new Date()
});
// If dynamic column/table names are required (rare), validate against a strict allowlist
const allowedColumns = new Set(['ldap_dn', 'group_name', 'synced_at']);
if (!allowedColumns.has(columnName)) {
throw new Error('Invalid column');
}
// Still use parameterization for values; avoid interpolating identifiers directly
3. Validate and normalize inputs
Apply strict validation on inputs that feed LDAP filters or SQL identifiers. For identifiers like usernames or group names, use allowlists and length checks. In AdonisJS, you can leverage the validator:
import { schema } from '@ioc:Adonis/Core/Validator';
const loginSchema = schema.create({
username: schema.string({}, [ rules.regex(/.{1,64}/) ]),
password: schema.string({}, [ rules.minLength(8) ])
});
const validated = await validator.validate({ schema: loginSchema, from: 'body' });
const { username } = validated;
4. Limit LDAP metadata stored in CockroachDB
Only store non-sensitive mappings necessary for application logic. Avoid persisting raw LDAP filters or credentials. If group memberships are cached, ensure they are refreshed using safe, parameterized queries.
middleBrick’s scans can verify that inputs used in LDAP-related endpoints are properly validated and that SQL queries involving LDAP metadata use safe patterns. The scanner checks align with OWASP API Top 10 and can map findings to compliance frameworks relevant to identity management.