security - ctf ldap injection
Prevención de la inyección de LDAP (4)
Estoy trabajando en mi primera aplicación de escritorio que consulta LDAP. Estoy trabajando en C bajo unix y usando opends, y soy nuevo en LDAP. Después de un rato de trabajo, noté que el usuario podía alterar la consulta LDAP inyectando código malicioso.
Me gustaría saber qué técnicas de desinfección se conocen, no solo para el desarrollo de C / unix sino en términos más generales, es decir, desarrollo web, etc.
Pensé que escapar de iguales y punto y coma sería suficiente, pero no estoy seguro.
Aquí hay un pequeño código para que pueda aclarar la pregunta:
String ldapSearchQuery = "(cn=" + $userName + ")";
System.out.println(ldapSearchQuery);
Obviamente, necesito desinfectar $ userName, como se indica en este ARTÍCULO DE OWASP
OWASP es una buena guía de seguridad que uso mucho y tiene un código de ejemplo (en Java, pero debería poder traducir): http://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java
Además, aquí hay una referencia específica de Active Directory: http://www.rlmueller.net/CharactersEscaped.htm
Si está utilizando Spring, hay una clase LdapEncoder
( https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/support/LdapEncoder.html ) que proporciona métodos para valores de codificación en un filtro y DNs. Esta clase está realmente presente en al menos dos bibliotecas de spring, spring-ldap-core y spring-security-ldap. Y dos veces en el segundo :)
Y esta es mi traducción en C # de las funciones de escape en el blog mencionado por @TrueBlood.
/// <summary>
/// Escape a string for usage in an LDAP DN to prevent LDAP injection attacks.
/// There are certain characters that are considered special characters in a DN.
/// The exhaustive list is the following: '','',''/',''#'',''+'',''<'',''>'','';'',''"'',''='', and leading or trailing spaces
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public static string EscapeForDN(string name)
{
StringBuilder sb = new StringBuilder();
if (name.Length > 0 && ((name[0] == '' '') || (name[0] == ''#'')))
{
sb.Append(''//'); // add the leading backslash if needed
}
for (int i = 0; i < name.Length; i++)
{
char curChar = name[i];
switch (curChar)
{
case ''//':
sb.Append(@"//");
break;
case '','':
sb.Append(@"/,");
break;
case ''+'':
sb.Append(@"/+");
break;
case ''"'':
sb.Append("///"");
break;
case ''<'':
sb.Append(@"/<");
break;
case ''>'':
sb.Append(@"/>");
break;
case '';'':
sb.Append(@"/;");
break;
default:
sb.Append(curChar);
break;
}
}
if (name.Length > 1 && name[name.Length - 1] == '' '')
{
sb.Insert(sb.Length - 1, ''//'); // add the trailing backslash if needed
}
return sb.ToString();
}
/// <summary>
/// Escape a string for usage in an LDAP DN to prevent LDAP injection attacks.
/// </summary>
public static string EscapeForSearchFilter(string filter)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < filter.Length; i++)
{
char curChar = filter[i];
switch (curChar)
{
case ''//':
sb.Append("//5c");
break;
case ''*'':
sb.Append("//2a");
break;
case ''('':
sb.Append("//28");
break;
case '')'':
sb.Append("//29");
break;
case ''/u0000'':
sb.Append("//00");
break;
default:
sb.Append(curChar);
break;
}
}
return sb.ToString();
}
Ya tienes tu respuesta en el comentario de la pregunta. RFC 2254 lo tiene.
Esto es lo que uso en PHP. Algo equivalente en tu idioma debería bastar.
/**
* Sanitizes ldap search strings.
* See rfc2254
* @link http://www.faqs.org/rfcs/rfc2254.html
* @since 1.5.1 and 1.4.5
* @param string $string
* @return string sanitized string
* @author Squirrelmail Team
*/
function ldapspecialchars($string) {
$sanitized=array(''//' => ''/5c'',
''*'' => ''/2a'',
''('' => ''/28'',
'')'' => ''/29'',
"/x00" => ''/00'');
return str_replace(array_keys($sanitized),array_values($sanitized),$string);
}