软件供应链安全:源代码缺陷实例剖析
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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码值。