csharp.dotnet.security.audit.ldap-injection.ldap-injection

profile photo of returntocorpreturntocorp
Author
unknown
Download Count*

LDAP queries are constructed dynamically on user-controlled input. This vulnerability in code could lead to an arbitrary LDAP query execution.

Run Locally

Run in CI

Defintion

rules:
  - id: ldap-injection
    message: LDAP queries are constructed dynamically on user-controlled input. This
      vulnerability in code could lead to an arbitrary LDAP query execution.
    severity: ERROR
    metadata:
      likelihood: MEDIUM
      impact: MEDIUM
      confidence: MEDIUM
      category: security
      cwe:
        - "CWE-90: Improper Neutralization of Special Elements used in an LDAP
          Query ('LDAP Injection')"
      owasp:
        - A01:2017 - Injection
        - A03:2021 - Injection
      references:
        - https://owasp.org/Top10/A03_2021-Injection/
        - https://cwe.mitre.org/data/definitions/90
        - https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html#safe-c-sharp-net-tba-example
      subcategory:
        - vuln
      technology:
        - .net
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    languages:
      - csharp
    mode: taint
    options:
      taint_unify_mvars: true
    pattern-sources:
      - pattern-either:
          - pattern: $INPUT
          - pattern-inside: $T $M($INPUT,...) {...}
    pattern-sinks:
      - patterns:
          - pattern-either:
              - pattern: $S.Filter = ... + $INPUT + ...
              - pattern: $S.Filter = String.Format(...,$INPUT)
              - pattern: $S.Filter = String.Concat(...,$INPUT)
    pattern-sanitizers:
      - pattern-either:
          - pattern: Regex.Replace($INPUT, ...)
          - pattern: $ENCODER.LdapFilterEncode($INPUT)
          - pattern: $ENCODER.LdapDistinguishedNameEncode($INPUT)

Examples

ldap-injection.cs

public User Login(string userName, string password)
{
    using (DirectoryEntry entry = new DirectoryEntry(config.Path, config.UserDomainName + "\\" + userName, password))
    {
        using (DirectorySearcher searcher = new DirectorySearcher(entry))
        {
            // ruleid: ldap-injection
            searcher.Filter = String.Format("({0}={1})", SAMAccountNameAttribute, userName);
            searcher.PropertiesToLoad.Add(DisplayNameAttribute);
            searcher.PropertiesToLoad.Add(SAMAccountNameAttribute);
            var result = searcher.FindOne();
            if (result != null)
            {
                var displayName = result.Properties[DisplayNameAttribute];
                var samAccountName = result.Properties[SAMAccountNameAttribute];
                
                return new User
                {
                    DisplayName = displayName == null || displayName.Count <= 0 ? null : displayName[0].ToString(),
                    UserName = samAccountName == null || samAccountName.Count <= 0 ? null : samAccountName[0].ToString()
                };
            }
        }
    }
}

public User Login(string userName, string password)
{
    using (DirectoryEntry entry = new DirectoryEntry(config.Path, config.UserDomainName + "\\" + userName, password))
    {
        using (DirectorySearcher searcher = new DirectorySearcher(entry))
        {
            // ok: ldap-injection
            searcher.Filter = String.Format("({0}={1})", Encoder.LdapFilterEncode(SAMAccountNameAttribute), Encoder.LdapFilterEncode(userName));
            searcher.PropertiesToLoad.Add(DisplayNameAttribute);
            searcher.PropertiesToLoad.Add(SAMAccountNameAttribute);
            var result = searcher.FindOne();
            if (result != null)
            {
                var displayName = result.Properties[DisplayNameAttribute];
                var samAccountName = result.Properties[SAMAccountNameAttribute];
                
                return new User
                {
                    DisplayName = displayName == null || displayName.Count <= 0 ? null : displayName[0].ToString(),
                    UserName = samAccountName == null || samAccountName.Count <= 0 ? null : samAccountName[0].ToString()
                };
            }
        }
    }
}