HIGH ldap injectionadonisjs

Ldap Injection in Adonisjs

How Ldap Injection Manifests in Adonisjs

LDAP injection in Adonisjs applications typically occurs when user input is concatenated directly into LDAP queries without proper sanitization. Adonisjs developers often use LDAP for authentication against Active Directory or other directory services, creating several vulnerable patterns.

The most common vulnerability appears in custom authentication providers. Consider this typical Adonisjs LDAP authentication code:

const { Authenticator } = use('Authenticator')
const User = use('App/Models/User')

class LdapAuthenticator {
  async authenticate(username, password) {
    const dn = `uid=${username},ou=users,dc=example,dc=com`
    const client = await this.getLdapClient()
    
    try {
      await client.bind(dn, password)
      return await this.findUserByDn(dn)
    } catch (error) {
      throw new Error('Invalid credentials')
    }
  }
}

This code is vulnerable because an attacker can inject LDAP metacharacters. A payload like username=john)(objectClass=* transforms the DN into:

uid=john)(objectClass=*),ou=users,dc=example,dc=com

This bypasses authentication by creating a wildcard search that matches any object.

Another Adonisjs-specific pattern appears in route handlers that construct LDAP filters:

Route.post('/api/search-users', async ({ request }) => {
  const { filter } = request.only(['filter'])
  
  const client = await getLdapClient()
  const searchFilter = `(cn=${filter})`
  const results = await client.search('ou=users', {
    filter: searchFilter,
    scope: 'sub'
  })
  
  return results
})

Here, a payload like filter=*)(cn=*))(|(cn=* creates:

(cn=*)(cn=*))(|(cn=*

This breaks out of the intended filter context and creates a disjunction that returns all users.

Adonisjs's Lucid ORM integration can also create LDAP injection points when developers mix database queries with LDAP operations. A common anti-pattern:

async function getUserProfile({ auth, request }) {
  const user = auth.user
  const { department } = request.only(['department'])
  
  const client = await getLdapClient()
  const filter = `(department=${department})`
  const results = await client.search(
    `uid=${user.username},ou=users,dc=example,dc=com`,
    { filter }
  )
  
  return results
}

An attacker supplying department=HR)(objectClass=* would modify the LDAP filter to potentially expose all user objects.

Adonisjs-Specific Detection

Detecting LDAP injection in Adonisjs applications requires examining both the codebase and runtime behavior. For static analysis, middleBrick's OpenAPI/Swagger spec analysis can identify vulnerable patterns by scanning your API definitions and finding endpoints that accept LDAP-related parameters.

When middleBrick scans an Adonisjs API endpoint, it specifically tests for LDAP injection by injecting payloads containing metacharacters like *, (, ), &, |, and null bytes into parameters that appear LDAP-related. The scanner constructs payloads based on the parameter names and values observed in your API.

For the vulnerable route example above, middleBrick would test with payloads like:

filter=*)(cn=*))(|(cn=*
filter=admin)(objectClass=*
filter=*)(uid=*))(|(uid=*

The scanner monitors responses for indicators of successful injection, such as:

  • Unexpectedly large result sets
  • Authentication bypass (returning user data without valid credentials)
  • LDAP-specific error messages revealing backend structure
  • Response time anomalies suggesting different query execution paths
  • Changes in response structure or content

middleBrick's black-box scanning approach is particularly effective for Adonisjs applications because it tests the actual running API without requiring source code access. The scanner sends these malicious payloads to your endpoints and analyzes the responses to determine if LDAP injection is possible.

For applications using the official @adonisjs/auth` package with LDAP providers, middleBrick specifically tests the authentication flow by attempting to authenticate with injected payloads and checking if authentication succeeds unexpectedly.

The CLI tool makes this detection accessible: middlebrick scan https://your-adonisjs-app.com/api/search-users will automatically test for LDAP injection along with other API security issues.

Adonisjs-Specific Remediation

Remediating LDAP injection in Adonisjs applications requires input validation and proper LDAP query construction. The most effective approach uses parameterized LDAP queries, similar to SQL prepared statements.

First, implement strict input validation using Adonisjs's validation system:

const { schema } = use('Schema')

class LdapSearchValidator {
  get rules() {
    return {
      filter: 'required|string|min:1|max:50|regex:^[a-zA-Z0-9\s-]+$'
    }
  }
  
  get messages() {
    return {
      'filter.regex': 'Filter contains invalid characters'
    }
  }
}

This validation ensures only alphanumeric characters, spaces, and hyphens are allowed, blocking LDAP metacharacters.

For the actual LDAP operations, use parameterized queries with the ldapjs library:

const ldap = require('ldapjs')

class SafeLdapClient {
  constructor(url) {
    this.url = url
  }
  
  async search(baseDn, filterPattern, params) {
    const client = await this.getClient()
    
    // Escape special LDAP characters in parameters
    const escapedParams = params.map(param => {
      return param.replace(/[\*()\&\|\x00]/g, (char) => {
        return `\${char.charCodeAt(0).toString(16).padStart(2, '0')}`
      })
    })
    
    // Use parameterized filter with proper escaping
    const filter = new ldap.PresenceFilter({
      attribute: 'objectClass'
    })
    
    // Construct safe filter using attribute-value assertions
    const safeFilter = new ldap.AndFilter({
      filters: escapedParams.map(param => {
        return new ldap.SubstringFilter({
          attribute: 'cn',
          initial: param
        })
      })
    })
    
    const options = {
      filter: safeFilter,
      scope: 'sub'
    }
    
    return new Promise((resolve, reject) => {
      client.search(baseDn, options, (err, res) => {
        if (err) return reject(err)
        
        const entries = []
        res.on('searchEntry', entry => entries.push(entry.object))
        res.on('error', reject)
        res.on('end', () => resolve(entries))
      })
    })
  }
}

In your Adonisjs route handlers, integrate this safely:

Route.post('/api/search-users', async ({ request, response }) => {
  const { filter } = request.only(['filter'])
  
  // Validate input
  const validation = schema.create({
    filter: schema.string({}, [rules.regex(/^[a-zA-Z0-9\s-]+$/)])
  })
  
  try {
    await validation.validateAsync({ filter })
  } catch (error) {
    return response.status(400).send({ error: 'Invalid filter format' })
  }
  
  // Use safe LDAP client
  const client = new SafeLdapClient(process.env.LDAP_URL)
  try {
    const results = await client.search(
      'ou=users,dc=example,dc=com',
      '(cn=*)',
      [filter]
    )
    return results
  } catch (error) {
    return response.status(500).send({ error: 'LDAP search failed' })
  }
})

For authentication, use Adonisjs's built-in authentication guards with proper LDAP integration rather than custom implementations:

const { Authenticator } = use('Authenticator')

class SecureLdapAuthenticator {
  async authenticate(username, password) {
    const sanitizedUsername = username.replace(/[\(\)\*\&\|\x00]/g, '')
    
    const dn = `uid=${sanitizedUsername},ou=users,dc=example,dc=com`
    const client = await this.getLdapClient()
    
    try {
      await client.bind(dn, password)
      return await this.findUserByDn(dn)
    } catch (error) {
      // Only catch authentication errors, not other LDAP errors
      if (error.code === 49) { // Invalid credentials
        throw new Error('Invalid credentials')
      }
      throw error
    }
  }
}

Finally, use middleBrick's continuous monitoring (Pro plan) to regularly scan your Adonisjs APIs for LDAP injection and other vulnerabilities. Set up GitHub Actions to run middleBrick scans in your CI/CD pipeline, failing builds if security scores drop below your threshold.

Frequently Asked Questions

How can I test if my Adonisjs API is vulnerable to LDAP injection?
Use middleBrick's self-service scanner by running middlebrick scan https://your-api.com or scanning through the web dashboard. The scanner tests for LDAP injection by sending payloads with LDAP metacharacters to your endpoints and analyzing responses for signs of successful injection. No credentials or setup required.
Does middleBrick scan Adonisjs applications for LDAP injection specifically?
Yes, middleBrick's black-box scanning tests Adonisjs APIs for LDAP injection among its 12 security checks. The scanner identifies endpoints that accept user input potentially used in LDAP queries and tests them with LDAP injection payloads. It works regardless of whether you're using the standard @adonisjs/auth package or custom LDAP implementations.