我目前正在使用Spring LDAP Filter子句或通过LdapEncoder.filterEncode()来正确转义我的过滤器。
与此同时,我正在使用WireShark来捕获在本地计算机和LDAP服务器之间交换的数据包。
我似乎有问题。即使我正确地逃避了值(我已通过调试确认),它们也会通过网络无法转义。我还确认(通过调试)该值一直保持编码,直到它进入javax.naming.InitialContext。
以下是一个示例(请注意,我使用的是Spring LDAP 1.3.0,这些都发生在Oracle JDK 6u45和Oracle JDK 7u45上)。
在我自己的代码中,在服务层上,正在进行的调用是:
String lMailAddress = (String) ldapTemplate.searchForObject("", new EqualsFilter(ldapUserSearchFilterAttribute, principal).encode(), new ContextMapper() {
@Override
public Object mapFromContext(Object ctx) {
DirContextAdapter lContext = (DirContextAdapter) ctx;
return lContext.getStringAttribute("mail");
}});
此时,我可以确认过滤器上的encode()方法返回的字符串是“(sAMAccountName = boi \ 2a)”
我可以调试代码的最后一点是以下内容(从org.springframework.ldap.core.LdapTemplate第229行开始):
SearchExecutor se = new SearchExecutor() {
public NamingEnumeration executeSearch(DirContext ctx) throws javax.naming.NamingException {
return ctx.search(base, filter, controls);
}
};
稍后调用executeSearch()时,我还可以验证过滤器字符串是否包含“(sAMAccountName = boi \ 2a)”。
我无法进一步调试,因为我没有javax的源代码,命名。*或com.sun.jndi.ldap。*(因为正在调用com.sun.jndi.ldap.LdapCtx)。< / p>
但是,一旦调用从executeSearch()返回,WireShark就会通知我包含带有过滤器“(sAMAccountName = boi *)”的searchRequest的LDAP数据包已被传输(*不再被转义)。 / p>
我使用了类似的编码,并使用了不同的LdapTemplate方法,产生了我期望的结果(我看到编码的滤波器在WireShark中传输),但我无法解释为什么,在我刚刚暴露的情况下,值被解码在传播之前。
请帮助我了解情况。 Hpoefully,我是在这里没有正确理解LDAP协议的人。
感谢。
免责声明:我已向Spring LDAP论坛发布了同样的问题。
TL / DR:为什么com.sun.jndi.ldap.LdapCtx在将LDAP编码过滤器(如\ 2a转换为*)传输到LDAP服务器之前将其解码?
更新:尝试并观察了与IBM的J9 JDK7相同的行为。
答案 0 :(得分:3)
虽然我不熟悉Spring LDAP,但听起来并不一定有理由担心。 LDAP过滤器不是以明文形式传输,而是以二进制编码传输,并且不需要在此机制中进行转义(这样做也不正确)。
我们以“(sAMAccountName = boi *)”为例。如上所述,此过滤器是子字符串过滤器,其subInitial组件为“boi”。正如您所指出的,如果您希望它是一个相等过滤器而不是子串过滤器,那么字符串表示必须是“(sAMAccountName = boi \ 2a)”。但是,这些过滤器的二进制编码不使用任何转义,而是使用ASN.1 BER类型来区分子字符串和相等过滤器。
如果你想要“(sAMAccountName = boi *)”作为子串过滤器,那么编码的表示将是:
a417040e73414d4163636f756e744e616d6530058003626f69
另一方面,如果你想“(sAMAccountName = boi \ 2a)”作为相等过滤器,编码将是:
a316040e73414d4163636f756e744e616d650404626f692a
编码的完整解释不是我想要进入的,但是第一个开头的“a4”表示它是子串滤波器,而第二个开头的“a3”表示这是一个相等的过滤器。
您应该能够验证WireShark中发送的实际字节数。很可能WireShark在生成字符串表示时没有正确地逃避过滤器,但这对WireShark本身来说是一个问题。目录服务器只获取二进制表示,很难相信LDAP服务器会误解它。
答案 1 :(得分:2)
OWASP建议对搜索字符串进行编码:
public static final String escapeLDAPSearchFilter(String filter) {
StringBuffer sb = new StringBuffer(); // If using JDK >= 1.5 consider using StringBuilder
for (int i = 0; i < filter.length(); i++) {
char curChar = filter.charAt(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);
}
}
return sb.toString();
}
DN字符串的转义不同。请参阅以下链接。
https://www.owasp.org/index.php/Preventing_LDAP_Injection_in_Java