validación usuarios usuario servidor petición para obtener los ldap_search formulario ejemplo directorio datos contraseña configurar conectar con autenticación aplicaciones activo active php ldap code-injection

usuarios - login directorio activo php



cómo protegerse contra la inyección de LDAP (5)

Estamos construyendo una aplicación que utiliza LDAP a través de php y llegué a la conclusión de que hay algo que se puede hacer con la inyección en LDAP y, aún mejor, ¿cómo se puede proteger contra las inyecciones de LDAP?


En la mayoría de los casos, está utilizando una cuenta de solo lectura para LDAP. Dado que LDAP es pobre en las actualizaciones de escritura, solo ocurre en secciones muy pequeñas de la aplicación donde se puede usar otra cuenta.

Incluso entonces, el lenguaje de consulta y el de actualización están completamente separados.

Para protegerse contra la visualización de información no deseada, trate todas las entradas del usuario como contaminadas y asegúrese de que los datos contaminados nunca se utilicen antes de analizarlos, limpiarlos y escapularlos adecuadamente y copiarlos en una variable limpia.

Del mismo modo, puede considerar solo seleccionar los datos que espera de la respuesta y devolverlos para su visualización.


Un elemento a considerar es que un LDAP se vincula con un Nombre de usuario (DN) pero ninguna contraseña se considera un enlace anónimo. Por lo tanto, si realiza una prueba para ver si las credenciales aprobadas pueden vincularse a través de LDAP para validar al usuario, si pasan una contraseña en blanco y usted la transmitió como está, podría dejar que alguien ingrese incorrectamente.


Al construir filtros LDAP, debe asegurarse de que los valores de filtro se manejen de acuerdo con RFC2254 :

Cualquier carácter de control con un código ACII <32 así como los caracteres con un significado especial en los filtros LDAP "*", "(", ")" y "/" (la barra invertida) se convierten en la representación de una barra invertida seguida por dos dígitos hexadecimales que representan el valor hexadecimal del personaje.

Zend_Ldap por ejemplo usa la siguiente rutina

//[...] $val = str_replace(array(''//', ''*'', ''('', '')''), array(''/5c'', ''/2a'', ''/28'', ''/29''), $val); for ($i = 0; $i<strlen($val); $i++) { $char = substr($val, $i, 1); if (ord($char)<32) { $hex = dechex(ord($char)); if (strlen($hex) == 1) $hex = ''0'' . $hex; $val = str_replace($char, ''//' . $hex, $val); } } //[...]


function ldap_quote($str) { return str_replace( array( ''//', '' '', ''*'', ''('', '')'' ), array( ''//5c'', ''//20'', ''//2a'', ''//28'', ''//29'' ), $str ); }


En PHP 5.6+ debe usar la función ldap_escape para valores de filtro y RDN. Como:

// Escaping an LDAP filter for ldap_search ... $username = ldap_escape($username, null, LDAP_ESCAPE_FILTER); $filter = "(sAMAccountName=$username)"; // Escaping a DN to be used in an ldap_add, or a rename... $rdn = ldap_escape(''Smith, John'', null, LDAP_ESCAPE_DN); $dn = "cn=$rdn,dc=example,dc=local";

Además, si acepta la entrada del usuario para nombres de atributos en las búsquedas, debe estar validando que es un OID o nombre de atributo aceptable. Puedes hacer eso con una función como esta:

/** * Validate an attribute is an OID or a valid string attribute name. * * @param string * @return bool */ function isValidAttributeFormat($value) { $matchOid = ''/^[0-9]+(/.[0-9]+?)*?$/''; $matchDescriptor = ''/^/pL([/pL/pN-]+)?$/iu''; return preg_match($matchOid, $value) || preg_match($matchDescriptor, $value); } $attribute = ''sAMAccountName''; $value = ''foo''; if (!isValidAttributeFormat($attribute)) { throw new /InvalidArgumentException(sprintf(''Invalid attribute name: %s'', $attribute)); } $value = ldap_escape($value, null, LDAP_ESCAPE_FILTER); $filter = "($attribute=$value)";