LDAP Injection

ID

csharp.ldap_injection

Severity

critical

Resource

Injection

Language

CSharp

Tags

CWE:90, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1

Description

Improper neutralization of special elements used in an LDAP query ('LDAP Injection').

Rationale

LDAP Injection is a type of attack that takes advantage of insufficient input validation in LDAP queries. The attacker manipulates these queries by supplying crafted input that can alter the intended execution logic. This is particularly dangerous in systems where LDAP is used for authentication, authorization, or retrieval of sensitive information.

For example, consider the following C# code that searches for a user in an LDAP directory:

using Microsoft.AspNetCore.Mvc;
using System.DirectoryServices;
using System.DirectoryServices.Protocols;

[ApiController]
[Route("api/[controller]")]
public class LdapService : ControllerBase
{
    [HttpGet]
    public DirectorySearcher GetUserSearcher(string username)
    {
        DirectoryEntry entry = new DirectoryEntry("LDAP://your.domain.com");
        DirectorySearcher searcher = new DirectorySearcher(entry);

        // VULNERABLE: user input is unsanitized
        searcher.Filter = $"(sAMAccountName={username})";
        return searcher;
    }
}

In this case, if userInput is not properly validated, an attacker could provide input like )(|(sAMAccountName=, turning the query into:

(sAMAccountName=*)(|(sAMAccountName=*)

This effectively broadens the search filter beyond the intended scope, potentially exposing all entries in the directory.

Remediation

The vulnerable code can be remediated by ensuring that user input is properly sanitized. The Microsoft.Security.Application.Encoder class provides a LdapFilterEncode() method that can be used escape special characters in LDAP filters:

using Microsoft.AspNetCore.Mvc;
using System.DirectoryServices;
using Microsoft.Security.Application;

[ApiController]
[Route("api/[controller]")]
public class LdapService : ControllerBase
{
    [HttpGet]
    public DirectorySearcher GetUserSearcher(string username)
    {
        DirectoryEntry entry = new DirectoryEntry("LDAP://your.domain.com");
        DirectorySearcher searcher = new DirectorySearcher(entry);

        // FIXED - Correctly escape input before using it in an LDAP filter
        string escapedUsername = Encoder.LdapFilterEncode(username);
        searcher.Filter = $"(sAMAccountName={escapedUsername})";
        return searcher;
    }
}

Please note that the Encoder class is no longer maintained. You may use the alternative LdapEncoder.FilterEncode() method in the AntiLdapInjection NuGet package.

Alternatively, a positive validation (e.g. using a regular expression) can check whether that user input is valid.

To remediate LDAP Injection vulnerabilities in software, you should employ the following best practices:

  1. Input Validation: Rigorously verify and validate all user inputs. Ensure the input meets expected formats and does not contain any special characters, unless explicitly allowed.

  2. Escaping and Sanitization: Use libraries or built-in functions to escape and sanitize user inputs before incorporating them into LDAP queries. You might consider using helper classes or third-party libraries that automate this process.

  3. Parameterized LDAP Queries: Where possible, use parameterized queries or prepared statements for LDAP operations. This approach helps separate user input from command logic, reducing the risk of injection.

  4. Least Privilege: Run LDAP queries using an account with the least privileges necessary for the operation. This limits potential exposure if an injection occurs.

  5. Regular Security Reviews and Testing: Conduct regular security reviews and utilize SAST to identify potential injections during the development cycle, addressing them before code reaches production.

By following these steps, you can significantly reduce the risk of LDAP Injection vulnerabilities in your applications, thereby enhancing the security and integrity of your systems.

Configuration

The detector has the following configurable parameters:

  • sources, that indicates the source kinds to check.

  • neutralizations, that indicates the neutralization kinds to check.

Unless you need to change the default behavior, you typically do not need to configure this detector.

References