Ldap Injection in Adonisjs with Firestore
Ldap Injection in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability
LDAP Injection is an injection attack that manipulates queries to an LDAP server. In AdonisJS applications that integrate Firestore as a primary data store, LDAP is often used for centralized authentication or group membership checks. When user-controlled input is concatenated into LDAP filter strings without sanitization or parameterized queries, an attacker can alter the filter logic to bypass authentication, extract sensitive data, or cause excessive queries.
Consider an AdonisJS service that builds an LDAP filter using string concatenation:
const buildFilter = (username) => `(&(objectClass=user)(uid=${username}))`;
If username comes directly from request input (e.g., query params or body), an attacker can supply admin)(uid=* to produce (&(objectClass=user)(uid=admin)(uid=*)), which can match all users or bypass intended access controls. This becomes a security boundary issue when the application uses LDAP to gate access to Firestore resources.
The risk is compounded when Firestore security rules rely on data fetched via LDAP. For example, an app may query LDAP to determine group membership and then allow Firestore reads based on group claims. If LDAP is abused via injection to falsely assert membership, an attacker can gain unauthorized access to Firestore documents. Additionally, LDAP queries triggered by untrusted input can lead to excessive requests or information disclosure through error messages, aiding further attacks.
AdonisJS does not inherently protect against LDAP injection; developers must treat LDAP inputs with the same care as SQL or NoSQL inputs. Because Firestore is often used for structured data and access control, ensuring that LDAP filters are built safely is critical to maintaining the integrity of authorization checks.
Firestore-Specific Remediation in Adonisjs — concrete code fixes
To prevent LDAP injection in AdonisJS when integrating with Firestore, avoid building LDAP filters via string concatenation. Use parameterized filters or a dedicated LDAP library that supports safe escaping. Below are concrete, Firestore-oriented examples for AdonisJS.
Unsafe approach (vulnerable):
// routes.ts
Route.get('/users/:username', async ({ params }) => {
const ldapClient = new LdapClient();
const filter = `(&(objectClass=user)(uid=${params.username}))`;
const user = await ldapClient.search(filter);
// Use Firestore after LDAP check
const doc = await Firestore.collection('users').doc(params.username).get();
return doc.data();
});
This approach is unsafe because params.username is directly interpolated into the LDAP filter string.
Safe approach using parameterized escaping:
// ldapUtils.ts
import { escapeFilter } from 'ldap-filter-escape';
export const buildSafeFilter = (username: string): string => {
const escaped = escapeFilter({ uid: username });
return `(&(objectClass=user)${escaped})`;
};
// routes.ts
Route.get('/users/:username', async ({ params }) => {
const filter = buildSafeFilter(params.username);
const ldapClient = new LdapClient();
const user = await ldapClient.search(filter);
if (!user) { throw new Error('Unauthorized'); }
const doc = await Firestore.collection('users').doc(params.username).get();
return doc.data();
});
The escapeFilter function ensures that special LDAP characters (such as *, (, ), and backslash) are properly encoded, preventing filter manipulation. This keeps the UID comparison literal and safe.
Alternative: Using a parameterized LDAP client:
// routes.ts
Route.get('/profile', async ({ auth }) => {
const username = auth.user.username;
const ldapClient = new LdapClient();
// Many LDAP libraries support structured filter arrays
const filter = {
and: [
{ objectClass: 'user' },
{ uid: username } // library handles escaping
]
};
const user = await ldapClient.search(filter);
const doc = await Firestore.collection('profiles').doc(username).get();
return doc.data();
});
When available, prefer libraries that accept filter objects rather than raw strings. This reduces the chance of accidental injection. Always validate and sanitize input before using it in LDAP or Firestore operations, and ensure that Firestore security rules do not implicitly trust LDAP-derived claims without additional verification.