摘录"理解LDAP与LDAP注入"

0x01 LDAP简介

        LDAP,轻量目录访问协议

           | dn: 一条记录的位置

           | dc: 一条记录所属区域

           | ou: 一条记录所属组织

           | cn/uid:一条记录的名字/ID

        这里拿LDAP和数据库进行比较。数据库用"表"来存数据,LDAP用"树"来村数据。数据库主要是三个DB,TABLE,ROW来定位一条记录,而LDAP首先要说明是那一棵树dc,然后是从树根到目的所经过的所有"分叉",ou(group),最后就是目标的名字,例如UID等等。

         具体到如何定义如下:

dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=waibo,dc=com
其中树根是dc=waibo,dc=com,分叉ou=bei,ou=xi,ou=dong,目标cn=honglv
注意:要把"cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org"看成是一个整体,它只是属性dn的值

        具体的一条记录如下:

dn:cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org
objectClass:organizationalPerson
cn:stan
cn:小刀
sn:小刀
description:a good boy

  (保存成LDIF文件,可以导入到LDAP数据库中)

0x02 LDAP基本语法

       1) =(等于)

           查找"名"属性为"John"的所有对象,可以使用:

(givenName=John)
这会返回"名"属性为"John"的所有对象。圆括号是必需的,以便强调LDAP语句的开始和结束。

        2) &(逻辑与)

        如果具有多个条件并且希望全部条件都得到满足,则可使用此语法。例如,如果希望查找居住在Dallas并且"名"为"John"的所有人员,可以使用:

(&(givenName=John)(l=Dallas))
此语句将查找"名"不为"John"的所有对象。请注意!操作符紧邻参数的前面,并且位于参数的圆括号内。由于本语句只有一个参数,因此使用圆括号将其括起来以示说明

         3) !(逻辑非)

             此操作符用来排除具有特定属性的对象。假定您需要查找"名"为"John"的对象以外的所有对象。则应使用如下语句:

(!givenName=John)
此语句将查找"名"不为"John"的所有对象。请注意:!操作符紧邻参数的前面,并且位于参数的圆括号内。由于本语句只有一个参数,因此使用圆括号将其括起来以示说明。

         4) *(通配符)

              可使用通配符表示值可以等于任何值。使用它的情况可能是:您希望查找具有职务头衔的所有对象。为此,可以使用:

(title=*)
这会返回"title"属性包含内容的所有对象。另一个例子是:您知道某个对象的"名"属性的开头两个字母是"Jo".那么,可以使用如下语句进行查找:
   (givename=Jo*)
      这会返回"名"以"Jo"开头的所有对象

          5) 高级用法eg:

             您需要一个筛选条件,用来查找居住在Dallas或Austin,并且名为"John"的所有对象。使用的语法应该是:

(&(givenName=John)(!(l=Dallas)(l=Austin)))

0x03 LDAP注入

     LDAP注入攻击和SQL注入攻击相似,接下来的想法是利用用户引入的参数生成LDAP查询。一个安全的Web应用的Web应用在构造和将查询发送给服务器前应该净化用户传入的参数。在有漏洞的环境中,这些参数没有得到合适的过滤,因而攻击者可以注入任意恶意代码。使用最广泛的LDAP:ADAM和OpenLDAP,下面的结论将会导致代码注入:

      3.1 引入

(attribute=value)

         如果过滤器用于构造查询单缺少逻辑操作符,如value)(injected_filter,瞬间导致产生了两个过滤器,

(attribute=value)(injected\_filter)

         通常,在OpenLDAP实施中,第二个过滤器会被忽略,只有第一个会被执行。而在ADAM中,有两个过滤器的查询是不被允许的,因而这个注入毫无用处。

(|attribute=value)(second_filter)) or (&(attribute=value)(second_filter))

          如果第一个用于构造查询的过滤器有逻辑操作符,形如value)(injected_filter)的注入会变成如下过滤器:

(&(attribute=value)(injected_filter)) (second_filter)。

          虽然过滤器语法上并不正确,OpenLDAP还是会从左到右进行处理,忽略第一个过滤器闭合后的任何字符。

          但是有的浏览器会进行检查,检查过滤器是否正确,这种情况下value)(injected_filter))(&(1=0,于是就出现了下述payload

(&(attribute=value)(injected_filter))(&(1=0)(second_filter))

           既然第二个过滤器会被LDAP服务器忽略,有些部分便不允许有两个过滤器的查询。这种情况下,只能构建一个特殊的注入以获得单个过滤器的LDAP查询,如value)(injected_filter得到

(&(attribute=value)(injected_filter)(second_filter))

       3.2 AND注入

             这种情况,应用汇构造由"&"操作符和用户引入的参数组成的正常查询在LDAP目录中搜索,例如:

(&(parameter1=value1) (parameter2=value))

             这里value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现他自己的目标。

           3.2.1 绕过访问控制

                 一个登陆页有两个文本框用于输入用户名和密码,过滤器如下:

(&(USER=Uname)(PASSWORD=Pwd))

                 如果攻击者输入一个有效地用户名,如r00tgrok,然后在这个名字后面注入恰当的语句,password检查就会被绕过。输入Uname=slisberger)(&)),得到如下

(&(USER=slisberger)(&)(PASSWORD=Pwd))

                 LDAP服务器只处理第一个过滤器,即仅查询(&(USER=slidberger)(&))得到了处理。这个查询永真,故成功绕过。

            3.2.2 权限提升

               现假设下面的查询会向用户列举出所有可见的低安全等级文档:

(&(directory=document)(security_level=low))

               这里第一个参数document是用户入口,low是第二个参数的值。如果攻击者想列举出所有可见的高安全等级的文档,他可以利用如下的注入: **document)(security_level=*))(&(directory=documents**得到:

(&(directory=documents)(security_level=*))(&(directory=documents)(security_level=low))

                LDAP服务器仅会处理第一个过滤器而忽略第二个,因而只有下面的查询会被处理:

(&(directory=documents)(security_level=*))

          3.3 OR注入

               这种情况,应用会构造由"|"操作符和用户引入的参数组成的正常查询在LDAP目录中搜索,例如:

(!(parameter1=value1) (parameter2=value2))

                这里value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现他自己的目标。

           3.4 LDAP盲注

              3.4.1 AND盲注

                假设一个Web应用想从一个LDAP目录列出所有可用的Epson打印机,错误信息不会反悔,应用发送如下的过滤器:

($(objectClass=printer)(type=Epson*))

                正确的过滤器为:

(&(objectClass=printer)(type=Epson*))

                而当注入)(objectClass=))(&(objectClass=void时得到

(&(objectClass=*)(objectClass=*))(&(objectClass=void)(type=Epson*))

                 执行第一个,过滤器objectClass=*总是返回一个对象。当图标被显示时响应为真,否则为假。这样我们就可以猜第二个括号的objectclass字段有些什么内容了。LDAP盲注技术让攻击者使用基于TRUE/FALSE的技术访问所有的信息。

              3.4.2 OR盲注

                这种情况下,用于推测想要的信息的逻辑与AND是相反的,因为使用的是OR逻辑操作符。

              3.4.3 盲注深入

                 攻击者可以使用字母、数字搜索提取属性的值,这个想法的关键在于将一个复杂的值转化为TRUE/FALSE列表。这个机制,通常称为booleanization,大意是二值化。

                  假设攻击者想知道department属性的值,处理如下:

(&(idprinter=HPLaserJet2100)(department=a*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=f*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=fa*)) (object=printer))

                  如此根据返回的不同结果猜是否正确,和MYSQL盲注类似。

                  同样,攻击者可以使用字符集削减技术减少获得信息所需的请求数,为完成这一点,他使用通配符测试给定的字符在值中是否为anywhere:

(&(idprinter=HPLaserJet2100)(department=*b*))(object=printer))
(&(idprinter=HPLaserJet2100)(department=*n*))(object=printer))

                  这样子可以看department中是否有b和n,巧用可以加速猜解过程,当然一般肯定都是写脚本猜解

0x04 防御LDAP注入

     总而言之,我们看到圆括号、星号、逻辑操作符、关系运算操作符在应用层都必须过滤。无论什么时候,只要可能,构造LDAP搜索过滤器的值在发送给LDAP服务器查询之前都要用应用层有效地值列表来核对。正则表达式替换掉就可以了。


你可能感兴趣的:(摘录"理解LDAP与LDAP注入")