在传输之前Java解码编码的LDAP过滤器?防止 LDAP 注入(inject)

标签 java security spring-security ldap spring-ldap

我目前正在正确转义我的过滤器,无论是使用 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,naming.* 或 com.sun.jndi.ldap.* 的源代码(因为正在调用 com.sun.jndi.ldap.LdapCtx)。

但是,一旦调用从executeSearch() 返回,WireShark 就会通知我包含带有过滤器“(sAMAccountName=boi*)”的searchRequest 的LDAP 数据包已被传输(* 不再转义)。

我使用了类似的编码并使用了 LdapTemplate 的不同方法,产生了我期望的结果(我看到编码的过滤器在 WireShark 中传输),但我无法解释为什么在我刚刚暴露的情况下,该值被解码在传输之前。

请帮我了解一下情况。幸好我是一个没有正确理解 LDAP 协议(protocol)的人。

谢谢。

免责声明:我已将同样的问题发布到 Spring LDAP 论坛。

TL/DR:为什么 com.sun.jndi.ldap.LdapCtx 在将 LDAP 编码过滤器(如\2a 到 *)传输到 LDAP 服务器之前对其进行解码?

更新:尝试并观察到 ​​IBM 的 J9 JDK7 具有相同的行为。

最佳答案

虽然我不熟悉 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 服务器会误解它。

关于在传输之前Java解码编码的LDAP过滤器?防止 LDAP 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19431275/

相关文章:

java - 如何调试spring依赖顺序?

java - 如何在不使用递归的情况下实现双向实体引用,示例如下

java - 通过处理程序调用 Activity 内的另一个 Activity 函数不起作用

java - 无法覆盖 Kotlin 中的 Java 函数

php - 这段 PHP 代码是否存在安全漏洞?

hibernate - hibernate命名查询可以防止SQL注入(inject)攻击吗?

grails - spring-security-core 插件的依赖问题

java - 仅使用 XML 配置的 Spring RESTful Web 服务

macos - Mac代码签名: Bypass the Keychain Access private key prompt from Terminal

Spring ,属性文件,空值