CVE-2014-125083 (published 2023-01-19T10:15Z)

A vulnerability has been found in Anant Labs google-enterprise-connector-dctm up to 3.2.3 and classified as critical. Affected by this vulnerability is an unknown functionality. The manipulation of the argument username/domain leads to sql injection. The patch is named 6fba04f18ab7764002a1da308e7cd9712b501cb7. It is recommended to apply a patch to fix this issue. The associated identifier of this vulnerability is VDB-218911.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/AnantLabs/google-enterprise-connector-dctm
commit_details: repo_url: https://github.com/AnantLabs/google-enterprise-connector-dctm
author: jlacey@google.com
author_date: 2014-03-14 08:29:27+00:00
msg: Escape username and domain values to avoid SQL injection in string
concatenation (b/13399766, 2 of 2).

Code review: https://codereview.appspot.com/75770044
repository: repo_url: https://github.com/AnantLabs/google-enterprise-connector-dctm
repo_name: AnantLabs/google-enterprise-connector-dctm
description: Automatically exported from code.google.com/p/google-enterprise-connector-dctm
repo_language: Java
owner: AnantLabs
file_changes: filename: DctmAuthenticationManager.java
change_type: ModificationType.MODIFY
diff: @@ -139,14 +139,15 @@ public class DctmAuthenticationManager implements AuthenticationManager {
       StringBuilder queryBuff = new StringBuilder();
       queryBuff.append("select user_name, user_ldap_dn from ");
       queryBuff.append("dm_user where user_login_name = '");
-      queryBuff.append(userLoginName);
+      queryBuff.append(DqlUtils.escapeString(userLoginName));
       if (!domainName.isEmpty()) {
         queryBuff.append("' and user_source = 'LDAP'");
         queryBuff.append(" and LOWER(user_ldap_dn) like '%,");
-        queryBuff.append(domainName);
+        queryBuff.append(DqlUtils.escapePattern(domainName.toString(), '\\'));
         if (domainName.size() == 1) { // NetBIOS domain
           queryBuff.append(",%");
         }
+        queryBuff.append("' escape '\\");
       }
       queryBuff.append("'");
 

programming_language: Java
filename: DqlUtils.java
change_type: ModificationType.MODIFY
diff: @@ -57,6 +57,56 @@ public class DqlUtils {
     buffer.append(')');
   }
 
+  /**
+   * Escapes single quotes (') in the given value by doubling them,
+   * as per SQL.
+   */
+  public static String escapeString(String value) {
+    StringBuilder buffer = new StringBuilder(value.length() + 2);
+    for (int i = 0; i < value.length(); i++) {
+      char c = value.charAt(i);
+      switch (c) {
+        case '\'':
+          buffer.append("''");
+          break;
+        default:
+          buffer.append(c);
+          break;
+      }
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Escapes single quotes (') in the given value by doubling them, as
+   * per SQL, and escapes the LIKE wildcards, percent (%) and
+   * underscore (_), using the given escape character, as well as
+   * escaping the escape character itself.
+   */
+  public static String escapePattern(String value, char escapeChar) {
+    StringBuilder buffer = new StringBuilder(value.length() + 2);
+    for (int i = 0; i < value.length(); i++) {
+      char c = value.charAt(i);
+      switch (c) {
+        case '\'':
+          buffer.append("''");
+          break;
+        case '%':
+        case '_':
+          buffer.append(escapeChar);
+          buffer.append(c);
+          break;
+        default:
+          if (c == escapeChar) {
+            buffer.append(escapeChar);
+          }
+          buffer.append(c);
+          break;
+      }
+    }
+    return buffer.toString();
+  }
+
   /** This class should not be instantiated. */
   private DqlUtils() {
     throw new AssertionError();

programming_language: Java
filename: DctmMockAuthenticationManagerTest.java
change_type: ModificationType.MODIFY
diff: @@ -369,6 +369,21 @@ public class DctmMockAuthenticationManagerTest extends TestCase {
     testParentDomainFail("ldapuser", "example.com");
   }
 
+  public void testSqlInjection_userNoDomain() throws Exception {
+    testDomainFail("' or user_name = 'localuser", "");
+  }
+
+  public void testSqlInjection_userDomain() throws Exception {
+    testDomainFail(
+        "ldapuser' and user_ldap_dn like '%dc=ajax,dc=example,dc=com,dc=au' --",
+        "ajax.example.com");
+  }
+
+  /** The post-processing using LdapName also blocks this. */
+  public void testSqlInjection_domain() throws Exception {
+    testDomainFail("ldapuser", "acme.example%");
+  }
+
   private Collection<String> toStrings(Collection<?> groups) {
     if (groups == null) {
       return null;

programming_language: Java
filename: DqlUtilsTest.java
change_type: ModificationType.ADD
diff: @@ -0,0 +1,81 @@
+// Copyright 2014 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.enterprise.connector.dctm;
+
+import junit.framework.TestCase;
+
+public class DqlUtilsTest extends TestCase {
+  public void testEscapeString_null() {
+    try {
+      DqlUtils.escapeString(null);
+      fail("Expected a NullPointerException");
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  public void testEscapeString_empty() {
+    assertEquals("", DqlUtils.escapeString(""));
+  }
+
+  public void testEscapeString_unescapedString() {
+    String value = "hello world";
+    assertEquals(value, DqlUtils.escapeString(value));
+  }
+
+  public void testEscapeString_unescapedPattern() {
+    String value = "\\ % _ \\\\ \\% \\_";
+    assertEquals(value, DqlUtils.escapeString(value));
+  }
+
+  public void testEscapeString_quoted() {
+    String value = "' \\ % _ \\' \\\\ \\% \\_";
+    assertEquals(value.replace("'", "''"), DqlUtils.escapeString(value));
+  }
+
+  public void testEscapePattern_null() {
+    try {
+      DqlUtils.escapePattern(null, '\\');
+      fail("Expected a NullPointerException");
+    } catch (NullPointerException expected) {
+    }
+  }
+
+  public void testEscapePattern_empty() {
+    assertEquals("", DqlUtils.escapePattern("", '\\'));
+  }
+
+  public void testEscapePattern_unescapedString() {
+    String value = "hello world";
+    assertEquals(value, DqlUtils.escapePattern(value, '\\'));
+  }
+
+  public void testEscapePattern_escapedPattern() {
+    String value = "\\ % _ \\\\ \\% \\_";
+    String escaped = "\\\\ \\% \\_ \\\\\\\\ \\\\\\% \\\\\\_";
+    assertEquals(escaped, DqlUtils.escapePattern(value, '\\'));
+  }
+
+  public void testEscapePattern_quoted() {
+    String value = "' \\ % _ \\' \\\\ \\% \\_";
+    String escaped = "'' \\\\ \\% \\_ \\\\'' \\\\\\\\ \\\\\\% \\\\\\_";
+    assertEquals(escaped, DqlUtils.escapePattern(value, '\\'));
+  }
+
+  public void testEscapePattern_quotedSlash() {
+    String value = "' \\ % _ \\' \\\\ \\% \\_";
+    String escaped = "'' /\\ /% /_ /\\'' /\\/\\ /\\/% /\\/_";
+    assertEquals(escaped, DqlUtils.escapePattern(value, '/'));
+  }
+}

programming_language: Java