注入LDAP

注入LDAP

LDAP(LightWeight Directory Access Protocol, 轻量级目录访问协议)用于访问网络中的目录服务。目录是一个分级结构的数据存储区,其中可能包含任何类型的信息,但常用于保存个人信息,如姓名、电话号码、电子邮件地址和工作职能等。Windows域中使用的Active Directory就是这种目录的一个典型示例。LDAP还常用在企业内联网Web应用程序中,如允许用户查看并修改雇员信息的人力资源应用程序。

每个LDAP查询使用一个或多个搜索过滤器,它们决定了请求返回的目录项。搜索过滤器可以使用各种逻辑运算符来表示复杂的搜索条件。最常用的搜索过滤器如下。

  • 简单匹配条件对单个属性的值进行匹配。例如,通过用户名搜索用户的应用程序可能使用以下过滤器:

    (username=daf)

  • 析取查询指定多个条件,返回的目录项必须满足其中任何一个条件。例如,在多个目录属性中查找用户提供的搜索项的搜索函数可能使用以下过滤器:

    (|(cn=searchterm) (sn=searchitem)(ou=searchterm))

  • 合取查询指定多个条件,返回的目录项必须满足所有这些条件。例如,LDAP中实施的登录机制可能使用以下过滤器:

    (&(username=daf)(password=secret))

和其他形式的注入一样,如果用户提交的输入不经任何确认即被插入到LDAP搜索过滤器中,攻击者就可以通过提交专门设计的输入来修改过滤器的结构,以检索数据或执行未授权操作。

一般而言,与SQL注入漏洞相比,LDAP注入漏洞更难以被攻击者利用,原因如下。

  • 搜索过滤器采用逻辑运算符来指定析取或合取查询的位置通常位于用户提交数据的插入位置之前,因而无法被修改。因此,简单匹配条件和合取查询不会受与SQL注入类似的“ or 1=1”类型的攻击。
  • 在常用的LDAP服务中,范湖IDE目录属性将作为搜索过滤器中的独立参数传递个LDAP API,并且通常在应用程序中进行了硬编码。因此,攻击者无法通过修改用户提交的输入来检索与查询检索的属性不同的属性。
  • 应用程序很少返回有用的错误消息,因此,通常攻击者只能“盲目”利用各种漏洞。

利用LDAP注入

尽管存在上述限制,但在许多情况下,攻击者仍然可以利用LDAP注入漏洞从应用程序中获取数据,或执行未授权操作。通常,实施这类攻击的方法与搜索过滤器的结构、用户输入的进入点,以及后端LDAP服务本身的执行细节密切相关。

析取查询

以允许用户查看指定业务部门的雇员的应用程序为例。其搜索结果仅限于用户获得授权可以查看的地理区域。例如,如果一名用户获得授权可以查看伦敦和雷丁区域,并且他搜索的是“销售”部门,应用程序将执行以下析取查询:

(|(department=London sales)(department=Reading sales))

这里应用程序构建了一个析取查询,并在用户提交的输入之前前置了一些表达式来执行所需的访问控制。

在这种情况下,攻击者可以通过提交以下搜索项对查询进行修改,以返回所有地区的所有雇员的资料:

)(department=*

*字符是LDAP中的通配符,可匹配任何数据项。如果将这个输入嵌入LDAP搜索过滤器中,应用程序将执行以下查询:

(|(department=London )(department=*)(department=Reading )(department=*))

由于这是一个析取查询并且包含通配符搜索项,因此,它会对所有目录项进行匹配。它会返回所有地区的所有员工的资料,从而突破应用程序的访问控制。

合取查询

这里我们以另一个类似的应用程序为例,同样,该应用程序允许用户按姓名在授权查看的地理区域内搜索雇员。

如果用户获得授权可以在伦敦进行搜索,并且他搜索姓名daf,则应用程序将执行以下查询:

(&(giveName=daf)(department=London))*

这里,用户的输入被插入到合取查询中,该查询的第二部分仅通过匹配其中一个伦敦部门的数据项来执行所需的访问控制。

在这种情况下,根据后端LDAP服务的执行细节,攻击者可以成功实施两种类型的攻击。一些LDAP允许批量使用多个搜索过滤器,并且选择性地应用这些过滤器(换言之,应用程序将返回与任意过滤器匹配的目录项)例如,攻击者可以提交以下输入:

***))(&giveName=daf**

如果将这个输入嵌入原始搜索过滤器中,将得到以下查询:

(&(giveName=*))(&giveName=daf)(department=London)*

现在,这个查询中包含两个搜索过滤器,第一个过滤器包含一个通配符匹配条件。因此,应用程序将返回所有地区的所有雇员的资料,从而避开了应用程序的访问控制。

第二种针对合取查询的额共计利用许多LDAP服务在处理NULL字节方面存在的漏洞。由于这些服务通常以本地代码编写,因此,搜索过滤器中的NULL字节将立即终止字符串,NULL之后的任何字符将被忽略。虽然LDAP本身并不支持注释,但是,攻击者可以利用它在处理NULL字节上的这个漏洞,从而“注释掉”查询的剩余部分。

在前一个示例中,攻击者可以提交以下输入:

***))%00**

应用程序服务器会将%00序列解码成原义NULL字节,因此,如果将以上输入嵌入到搜索过滤器中,查询将变为:

(&(giveName=*))[NULL](department=London*)

由于这个过滤器在NULL字节处被截短,在LDAP看来,其中只包含一个通配符条件,因此,应用程序还会返回伦敦地区以外的部门的所有雇员资料。

查找LDAP注入漏洞

向一项LDAP操作提交武侠ode输入并不会生成任何详细的错误消息。通常,由搜索功能返回的结果和发生的错误都有助于确定漏洞。但是,可以使用以下步骤相对可靠的确定LDAP注入漏洞。

  1. 尝试仅输入*字符作为搜索项。在LDAP中,这个字符是一个通配符,但在SQL中不是,如果返回大量结果,这种情况明显表示攻击针对的是一个LDAP查询

  2. 尝试输入大量的闭括号:

    )))))))

    这个输入将结束任何括住输入、以及那些包含主查询过滤器的括号,导致无法匹配的闭括号,因而破坏查询的语法。如果发生错误,应用程序就易于受到LDAP注入。

  3. 尝试输入各种旨在干扰不同类型的查询的表达式,并看是否可以通过这些表达式来影响返回的结果。所有LDAP均支持cn属性,如果对所查询的目录一无所知,使用该属性会大有用处。例如:

    )(cn=*

    ***))(|(cn=***

    ***))%00**

防止LDAP注入

如果有必要在一个LDAP查询中插入用户提交的输入,也只提交可事实严格输入确认的简单数据。应根据一份可接受字符“白名单”检查用户输入,其中最好只包括字母数字字符。应组织任何可能破坏LDAP查询的字符,包括 ( ) ; , * | & = 和空字节。拒绝任何与白名单不匹配的输入,不要净化。

0%