LDAP是Lightweight Directory Access Protocol , 即轻量级目录访问协议, 用这个协议可以访问提供目录服务的产品,例如OpenLDAP。

比如公司的员工列表名单, 对于一个员工你能查到他的电话,工位,部门等各种信息, 这就是一个目录。目录存储数据的方式,不像我们熟知的关系数据库, 在数据都表中一行一行以树的方式存储。 比如一个人的信息是这样的:

LDAP 过滤关键字符 ldap未进行过滤会引起_LDAP 过滤关键字符

 

常见LDAP统一认证服务,我们可以基于LDAP实现单点登录:

LDAP 过滤关键字符 ldap未进行过滤会引起_目录服务_02

 

安全问题

LDAP 注入是利用用户引入的参数生成恶意 LDAP 查询,通过构造 LDAP 过滤器来绕过访问控制、用户权限提升。在维持正常过滤器的情况下构造出 AND、OR 操作注入来获得敏感信息。

 

LDAP语法

search语法:attribute operator value search filter options:( "&" or "|" (filter1) (filter2) (filter3) ...) ("!" (filter))

详细解释

=(等于)

查找”Name”属性为”John”的所有对象:

(Name=John)

这条语句会返回”name”为”john”的所有对象,以便强调LDAP语句的开始和结束

&(逻辑与)

如果具有多个条件,并且希望所有条件都能满足,则使用该语法。

(&(Name=John)(live=Dallas))

以上语句查询居住在Dallas,并且名为John的所有人员

!(逻辑非)

此操作符用来排除具有特定属性的对象:

(!Name=John)

查找所有”name”不为”John”的人员

通配符 *

可以用通配符表示值可以等于任何内容

(title=*)

查找具有职务头衔的所有人员

(Name=Jo*)

查找所有”Name”以”Jo”开头的人员

最后,举一个较复杂的例子:

(&(Name=John)(|(live=Dallas)(live=Austin)))

查找所有居住在Dallas或Austin,并且名为John的人员。

最佳实践文档https://ldapwiki.com/wiki/Best%20Practices%20for%20LDAP%20Security

LDAP注入

可以搞个靶场进行练习。

LDAP注入举栗

AND LDAP注入

当后端的代码如下

(&(parameter1=value1)(parameter2=value2))

这里value1和value2都会被查询,其中value1和value2是用户可控的,如果过滤不完善,就会存在LDAP注入的可能。

比如一个用户登录的场景,用户输入username和password,应用会构造一个过滤器并发给LDAP服务器进行查询。

(&(username=uname)(password=pwd))

当用户输入一个有效的用户名,例如admin,那么就有可能在username字段后面进行注入,从而在不知道密码的情况下进行登陆。

payload: admin)(&)) result: (&(username=admin)(&))(password=123))

LDAP服务器只会处理第一个过滤器,而第一个过滤器永真,因此绕过了登录框

OR LDAP注入

当后端代码如下:

(|(parameter1=value1)(parameter2=value2))

一个典型的OR LDAP注入的场景就是:

假设一个资源管理器允许用户了解系统中可用的资源(打印机、扫描器、存储系统等)。用于展示可用资源的查询为:

(|(type=Rsc1)(type=Rsc2))

Rsc1和Rsc2表示系统中不同种类的资源,例如,Rsc1=printer,Rsc2=scanner用于列出系统中所以可用的打印机和扫描器。

payload: Rsc1=printer)(uid=*) result: (|(type=printer)(uid=*))(type=scanner))

LDAP服务器会响应所有的打印机和用户对象

LDAP盲注

LDAP AND盲注

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

(&(objectclass=printer)(type=Epson*))
 
使用这个查询,如果有可用的Epson打印机,其图标就会显示给客户端,否则没有图标出现。如果攻击者进行LDAP盲注入攻击*)(objectClass=*))(&(objectClass=void,Web应用会构造如下查询:
 
(&(objectclass=*)(objectClass=*))(&(objectClass=void)(type=Epson*))
 
仅对第一个过滤器进行处理:
 
(&(objectclass=*)(objectClass=*))
 
结果是,打印机的图标会一定显示出来,因为该查询永远会有结果,过滤器objectClass=*总是返回一个对象。当图标被显示时响应为真,否则为假。
例如构造如下的注入:
 
(&(objectClass=*)(objectClass=users))(&(objectClass=foo)(type=Epson*))

(&(objectClass=*)(objectClass=resources))(&(objectClass=foo)(type=Epson*))

这种代码注入的设置允许攻击者推测可能存在于LDAP目录服务中不同对象类的值。当响应Web页面至少包含一个打印机图标时,对象类的值就是存在的,另一方面而言,如果对象类的值不存在或没有对它的访问,就不会有图标出现。

LDAP OR盲注

这种情况下,用于推测想要的信息的逻辑是相反的,因为使用的是OR逻辑操作符。接下来使用的是同一个例子,OR环境的注入为:

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

这个LDAP查询没有从LDAP目录服务获得任何对象,打印机的图标也不会显示给客户端(FALSE)。如果在响应的Web页面中有任何图标,则响应为TRUE。故攻击者可以注入下列LDAP过滤器来收集信息:

(|(objectClass=void)(objectClass=users))(&(objectClass=void)(type=Epson*))
(|(objectClass=void)(objectClass=resources))(&(objectClass=void)(type=Epson*))

owasp官方文档https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html

 

LDAP安全防护

LDAP过滤器的结构和使用得最广泛的LDAP:ADAM和OpenLDAP

1、服务端对输入内容的合法性进行验证,检查提交的数据是否包含特殊字符,对特殊字符进行编码转换。

2、对于系统出现的错误信息,使用统一的错误页面,屏蔽系统本身的出错信息。

3、参数化XPath查询,将需要构建的XPath查询表达式,以变量的形式表示,变量不是可以执行的脚本。

4、通过MD5、SSL等加密算法,对于数据敏感信息和在数据传输过程中加密,即使某些非法用户通过非法手法获取数据包,看到的也是加密后的信息。

总结下就是:限制提交非法字符,对输入内容严格检查过滤,参数化XPath查询的变量。

 

 

参考:https://cloud.tencent.com/developer/article/1584896