
2.5 LDAP注入
2.5.1 LDAP注入的概念
LDAP(Lightweight Directory Access Portocol)是基于X.500标准的轻量级目录访问协议,提供访问目录数据库方法的服务和协议,常与目录数据库组成目录服务。目录是一个为查询、浏览和搜索而优化的树状组织结构,类似于Linux/UNIX系统中的文件目录。LDAP是一个标准、开放的协议,具有平台无关性。可以存储在其他条件下很难存储的管理信息,故公用证书、安全密钥、公司的物理设备信息等修改并不频繁的数据适合存储在目录中。我们可以将LDAP理解为一种搜索协议,类似于SQL,拥有查询语法,也存在注入攻击的风险。LDAP注入指在客户端发送查询请求时,输入的字符串中含有一些特殊字符,导致LDAP本来的查询结构被修改,从而允许访问更多未授权数据的一种攻击方式。本节分析LDAP注入产生的原因、危害以及修复方法。
2.5.2 LDAP注入的危害
LDAP注入可以利用用户引入的参数生成恶意LDAP查询,通过构造LDAP过滤器来绕过访问控制、提升用户权限。也可以在维持正常过滤器的情况下,通过构造AND、OR操作注入,获得敏感信息。CVE中也有一些与之相关的漏洞信息,如表2-5所示。
表2-5 与LDAP注入相关的漏洞信息

2.5.3 实例代码
本节使用实例的完整源代码可参考本书配套资源文件夹,源文件名:CWE90_LDAP_Injection__connect_tcp_01.java。
1)缺陷代码
代码片段1:


代码片段2:


上述代码的第39~61行,程序进行tcp连接、读取socket的数据并赋值给变量data,在第117行动态构造了一个LDAP查询语句,在第119行对其加以执行。LDAP为人员组织机构封装了常见的对象类,如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性。该查询的目的是验证是否存在名为变量data的员工信息,但并未对变量data的内容做任何过滤。使用简单的注入方式,令传入参数的值为“*”,则构造的动态查询条件为“(cn=*)”,这样可以查询到所有员工的信息,导致信息泄露。
2)修复代码


上述修复代码的第118行使用javax.naming.ldap包的扩展类BasicControl接收需要被处理的参数,第119行的control对象调用getEncodedValue()方法将接收的参数data进行编码,编码后的值为字符对应的ASN.1 BER编码值。编码后的字节数组不存在参与命令解析的特殊字符,可以构造结构、内容正常的LDAP查询语句,这样就避免了LDAP注入的发生。
2.5.4 如何避免LDAP注入
LDAP注入的根本原因是攻击者提供了可以改变LDAP查询含义的LDAP元字符。构造LDAP筛选器时,程序员应清楚哪些字符需作为命令解析,哪些字符需作为数据解析。为了防止攻击者侵犯程序员的各种预设情况,可使用白名单的方法,确保LDAP查询中由用户控制的内容完全来自预定的字符集合,不包含任何LDAP元字符。如果用户控制的内容范围要求必须包含LDAP元字符,那么应使用相应的编码机制转义这些元字符在LDAP查询中的意义。例如,&、!、|、=、<、>、,、+、-、"、'、;这些字符在正常情况下不会用到,但如果在用户的输入中出现了,那么就需要用反斜杠符号进行转义处理。还有些字符,如(、)、\、*、/、NUL,不仅需要用反斜杠符号处理,还要将字符变成相应的ASCII码值。