LDAP注入攻击
什么是LDAP?
LDAP(Lightweight Directory Access Protocol)轻量级目录访问协议,是一种在线目录访问协议,主要用于目录中资源的搜索和查询,是X.500的一种简便的实现。
------“X.500是构成全球分布式的名录服务系统的协议。X.500组织起来的数据就象一个很全的电话号码簿,或者说一个X.500系统象是一个分门别类的图书馆。而某一机构建立和维护的名录数据库只是全球名录数据库的一部分。特点:分散维护,强大的搜索性能。”
换句话说LDAP是用于访问目录服务(特别是基于X.500的目录服务)的轻量级客户端服务器协议,它通过TCP/IP传输服务运行。关键的地方就在于,数据是存储在目录中,而不是数据库中。
最重要的区别就是目录适合于存放静态数据,它存储的数据无论在类型和种类较之数据库中的数据都要更为繁多,包括音频、视频、可执行文件、文本等文件,另外目录中还存在目录的递归。既然是存放不同类型的静态数据,那么目录服务在进行优化后更适宜于读访问,而非写、修改等操作。
上面这张图展示了LDAP的结构。MySQL数据库中的数据都是按记录一条条记录存在表中,而LDAP是树结构的,数据存储在叶子节点上。比如要描述上图baby这个节点:cn=baby,ou=marketing,ou=people,dc=mydomain,dc=org
LDAP的基本概念
条目(Entry)
条目,也叫记录项,是LDAP中最基本的颗粒,如同字典中的词条或者是数据中的记录。通常对LDAP的添加、删除、修改、搜索都是以条目为基本单位。
属性(Attribute)
每个条目都可以有很多属性,比如常见的人都有姓名、地址、电话等属性。每个属性都有名称及对应的值,属性值可以有单个、多个,比如一个人有多个邮箱。
对象类(Object)
对象类是属性的集合,LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。
通过对象类可以方便的定义条目类型。每个条目可以直接继承多个对象类,这样就继承了各种属性。如果2个对象类中有相同的属性,则条目继承后只会保留1个属性。对象类同时也规定了哪些属性是基本信息,即必要属性和可选属性。
跟Java中的Object类一样,LDAP的根对象类就叫做top。
LDAP基本语法
=(等于)
例如,若希望查找属性giveName值为张三的所有对象,可以使用(givenName=张三)。这会返回对应条件的所有对象。
&(逻辑与)
例如,若希望查找居住在西安并且givenName为张三的所有对象,可以使用(&(givenName=张三)(l=西安))。
注:每个参数都被属于其自己的圆括号括起来。整个 LDAP 语句必须包括在一对主圆括号中。操作符 & 表明,只有每个参数都为真,才会将此筛选条件应用到要查询的对象。
|(逻辑或)
例如,若希望查找属性givenName值为张三或李四的所有对象,可以使用(|(givenName=Jhon)(givenName=Jack))。
!(逻辑非)
例如,若需要查找givenName为张三的对象以外的所有对象。则应使用如下语句:(!givenName=张三)。
*(通配符)
可使用通配符表示值可以等于任何值。使用它的情况可能是:希望查找具有职务头衔的所有对象。为此,可以使用(title=*),会返回title属性包含内容的所有对象。
另一个例子是:若知道某个对象的givenName属性的开头两个字母是‘张’。那么,可以使用(givenName=张*)进行查找,会返回givenName以‘张’开头的所有对象。
search语法
attribute operator value search filter options:( “&” or “|” (filter1) (filter2) (filter3) …) ("!" (filter))
主要根据属性和值进行搜索,就如浏览网页时我们通常并不会直接浏览某个目录,而是其下存在的某个文件。
LADP的URL形式
例如:
ldap://austin.ibm.com/ou=Austin,o=IBM
ldap:///ou=Austin,o=IBM??sub?(cn=Joe Q. Public)
看得出来在URL中这里使用逗号分隔查询,而数据库查询则使用’&'号,这是LDAP特有的,另外这里o表示组织(organization),u表示单元(unit),cn表示country name。
常见的LDAP环境
LDAP服务是许多公司和机构日常操作的关键组成部分,目录服务如微软的Microsoft Active Directory,Novell E-Directory和RedHat Directory服务都基于LDAP协议。不过也有其他的应用和服务会利用LDAP服务。
这些应用和服务通常需要不同的目录(单独认证)来工作。例如,一个域需要一个目录,邮箱和销售列表也需要一个单独的目录,另外远程访问、数据库和其他Web应用都需要目录。基于LDAP服务的新目录有多种用途,用于作为用户认证的集中化信息容器和使能单点登录环境。这个场景通过减少管理的复杂度、提升安全性和容错能力而提高了生产力。基本上,基于LDAP服务的应用使用目录处于如下用途之一:访问控制、权限管理、资源管理。
由于LDAP服务对于公司网络的重要性,LDAP服务器通常和其他数据库服务器一起放置于后端。下图展示了部署公司网络的典型场景:
LDAP注入攻击面
AND注入
应用会构造由”&”操作符和用户引入的的参数组成的正常查询在LDAP目录中搜索,例如:
(&(parameter1=value1)(parameter2=value2))
这value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现攻击者自己的目标。
若为了验证客户端提供的user/password密钥对,构造如下LDAP过滤器并发送给LDAP服务器:
(&(USER=Uname)(PASSWORD=Pwd))
如果攻击者输入一个有效地用户名,如r00tgrok,然后在这个名字后面注入恰当的语句,password检查就会被绕过,使得Uname=slisberger)(&)),引入任何字符串作为Pwd值,构造如下查询并发送给服务器:
(&(USER= slisberger)(&)(PASSWORD=Pwd))
OR注入
这种情况,应用会构造由‘|’操作符和用户引入的的参数组成的正常查询在LDAP目录中搜索,例如:
(|(parameter1=value1)(parameter2=value2))
这里value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现他自己的目标。类似的,加入现在用于展示可用资源的查询为:
(|(type=Rsc1)(type=Rsc2))
Rsc1和Rsc2表示系统中不同种类的资源。如果攻击者输入Rsc=printer)(uid=*),则下面的查询被发送给服务器:
(|(type=printer)(uid=*))(type=scanner)
这样也会造成注入的产生。
盲注
SQL注入中有盲注,LDAP中也存在这种问题,假设攻击者可以从服务器的响应中推测出什么,尽管应用没有报出错信息,LDAP过滤器中注入的代码却生成了有效的响应或错误。攻击者可以利用这一行为向服务器请求正确的或错误的问题。
假设一个Web应用想从一个LDAP目录列出所有可用的Epson打印机,错误信息不会返回,应用发送如下的过滤器:
(&(objectClass=printer)(type=Epson*))
使用这个查询,如果有可用的Epson打印机,其图标就会显示给客户端,否则没有图标出现。如果攻击者进行LDAP盲注攻击:
*)(objectClass=*))(&(objectClass=void
Web应用会构造如下查询:
(&(objectClass=*)(objectClass=*))(&(objectClass=void)(type=Epson*))
仅第一个LADP过滤器会被处理:
(&(objectClass=*)(objectClass=*))
那么这样就和我们查询的初衷相违背了。
怎么发现LDAP注入漏洞
如何利用LADP注入漏洞
To be continue。。。。
参考文章:
https://ca0y1h.top/Web_security/basic_learning/24.%E6%B5%85%E8%B0%88LDAP%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB/
https://blog.csdn.net/leader_ww/article/details/4028672
https://wooyun.js.org/drops/LDAP%E6%B3%A8%E5%85%A5%E4%B8%8E%E9%98%B2%E5%BE%A1%E5%89%96%E6%9E%90.htm