gitlab.security_code_scan.SCS0026-1.SCS0031-1

unknown
Download Count*
License

LDAP injection attacks exploit LDAP queries to influence how data is returned by the LDAP, or in this case an Active Directory server.

It is recommended that newer applications use the System.DirectoryServices.AccountManagement API instead of DirectorySearcher API as it hides the complexity of querying LDAP directly. However, the AccountManagement API is still susceptible to LDAP injection if a user inputs LDAP queries, including LDAP filter characters such as *.

It is recommended that all input passed to LDAP querying systems encode the following values:

  • Any occurrence of the null character must be escaped as “\00”.
  • Any occurrence of the open parenthesis character must be escaped as “\28”.
  • Any occurrence of the close parenthesis character must be escaped as “\29”.
  • Any occurrence of the asterisk character must be escaped as “\2a”.
  • Any occurrence of the backslash character must be escaped as “\5c”.

Example code that safely encodes input for use in an LDAP query using the AccountManagement API:

using System.DirectoryServices.AccountManagement;

string EncodeLDAPString(string input) {
    // Note the \ character is replaced first
    char[] chars = new char[] { '\\', '\0', '(', ')', '*' };
    string[] encoded = new string[] { "\\5c", "\\00", "\\28", "\\29", "\\2a" };

    for (int i = 0; i < chars.Length; i++)
    {
        input = input.Replace(chars[i].ToString(), encoded[i]);
    }

    return input;
}

// unsafe, do not use without encoding first
string userInput = "Administrator";
PrincipalContext AD = new PrincipalContext(ContextType.Domain, "ad.example.dev");

UserPrincipal u = new UserPrincipal(AD);
string encodedUserName = EncodeLDAPString(userInput);

// The AD search term, encoded prior to calling search
u.SamAccountName = encodedUserName;

// Search for user
PrincipalSearcher search = new PrincipalSearcher(u);

// Use FindOne to only return a single result
UserPrincipal result = (UserPrincipal)search.FindOne();
search.Dispose();

// show some details
if (result != null) {
    Console.WriteLine("User: {0}", result.DisplayName);
} else {
    Console.WriteLine("user not found");
}

The same encoding method shown in EncodeLDAPString can also be used when using the older DirectorySearcher API.

For more information see OWASP's guide: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

Run Locally

Run in CI

Defintion

rules:
  - id: security_code_scan.SCS0026-1.SCS0031-1
    languages:
      - csharp
    patterns:
      - pattern-either:
          - patterns:
              - pattern: (DirectorySearcher $SOURCE).Filter = ...
              - pattern-not: (DirectorySearcher $SOURCE).Filter = "..."
          - patterns:
              - pattern: (DirectorySearcher $SOURCE).Path = ...
              - pattern-not: (DirectorySearcher $SOURCE).Path = "..."
    message: >
      LDAP injection attacks exploit LDAP queries to influence how data is
      returned by

      the LDAP, or in this case an Active Directory server.


      It is recommended that newer applications use the `System.DirectoryServices.AccountManagement`

      API instead of `DirectorySearcher` API as it hides the complexity of querying LDAP directly.

      However,

      the `AccountManagement` API is still susceptible to LDAP injection if a user inputs LDAP

      queries,

      including LDAP filter characters such as `*`.


      It is recommended that all input passed to LDAP querying systems encode the following values:


      - Any occurrence of the null character must be escaped as “\00”.

      - Any occurrence of the open parenthesis character must be escaped as “\28”.

      - Any occurrence of the close parenthesis character must be escaped as “\29”.

      - Any occurrence of the asterisk character must be escaped as “\2a”.

      - Any occurrence of the backslash character must be escaped as “\5c”.


      Example code that safely encodes input for use in an LDAP query using the `AccountManagement`

      API:

      ```

      using System.DirectoryServices.AccountManagement;


      string EncodeLDAPString(string input) {
          // Note the \ character is replaced first
          char[] chars = new char[] { '\\', '\0', '(', ')', '*' };
          string[] encoded = new string[] { "\\5c", "\\00", "\\28", "\\29", "\\2a" };

          for (int i = 0; i < chars.Length; i++)
          {
              input = input.Replace(chars[i].ToString(), encoded[i]);
          }

          return input;
      }


      // unsafe, do not use without encoding first

      string userInput = "Administrator";

      PrincipalContext AD = new PrincipalContext(ContextType.Domain, "ad.example.dev");


      UserPrincipal u = new UserPrincipal(AD);

      string encodedUserName = EncodeLDAPString(userInput);


      // The AD search term, encoded prior to calling search

      u.SamAccountName = encodedUserName;


      // Search for user

      PrincipalSearcher search = new PrincipalSearcher(u);


      // Use FindOne to only return a single result

      UserPrincipal result = (UserPrincipal)search.FindOne();

      search.Dispose();


      // show some details

      if (result != null) {
          Console.WriteLine("User: {0}", result.DisplayName);
      } else {
          Console.WriteLine("user not found");
      }

      ```


      The same encoding method shown in `EncodeLDAPString` can also be used when using the

      older `DirectorySearcher` API.


      For more information see OWASP's guide:

      https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html
    severity: WARNING
    metadata:
      shortDescription: Improper neutralization of special elements used in an LDAP
        query ('LDAP Injection')
      category: security
      cwe: CWE-90
      primary_identifier: security_code_scan.SCS0026-1.SCS0031-1
      secondary_identifiers:
        - name: SCS0026
          type: security_code_scan_rule_id
          value: SCS0026
        - name: SCS0031
          type: security_code_scan_rule_id
          value: SCS0031
      license: MIT
      vulnerability_class:
        - Other