本系列文章主旨在于介绍一些漏洞类型产生的基本原理,探索最基础的解决问题的措施,不排除有些语言或者系统提供的安全的API可以更好地更直接地解决问题,也不排除可以严格地输入验证来解决。
LDAP是Lightweight Directory Access Protocol的缩写,即轻型目录访问协议。该协议可以访问支持X.500模型的目录产品,同时,又避免了X.500目录访问协议(DAP)过大的资源消耗。目前关于LDAP查询有两个标准:RFC 1960是针对LDAP V2的,RFC 2254定义了一个语法,关于如何在LDAP V3上建立一个搜索过滤器,并扩展至RFC 1960(LDAP V2)。了解详细信息,可以去阅读具体标准。
LDAP搜索过滤器是用波兰表示法建立的,也称为前缀表示法。例如:"cn=tom&userPassword=pass",会表示为"(&(cn=tom)(userPassword=pass))"。LDAP注入问题,就在使用收到的字符串组装查询时,由于输入的字符串中含有一些特殊字符,导致LDAP本来的查询结构被篡改,从而使得可以访问更多的未授权数据。一般,LDAP都会只开放查询操作,所以,一般不会增删改的操作。所以,相对SQL注入而言,它一般会导致验证绕过或者信息泄露。
要了解LDAP的查询操作,就需要了解LDAP的运算符,运算符的具体列表如下表:
运算符种类 | 运 算 符 |
逻辑运算符 | AND "&" |
OR "|" | |
NOT "!" | |
关系运算符 | <=, >=, =, ~= |
通配符 | * |
成组括号 | () |
由于这些逻辑运算符和通配符都有特殊的意义,所以,输入的内容里如果含有这些特殊字符而没有处理,就会导致LDAP注入攻击。以查询用户的例子来看,查询用户时,如果输入的名字是*, 那么查询的过滤器就是(cn=*),由于* 是匹配任何字符,所以,根据此条件可以获得所有用户的信息。 同样, 一个用户登录,需要根据用户名和密码来检测用户是否能够登录,用户输入的名字是:tom,密码是:pass,则查询过滤器是:&(cn="tom")(password="pass"), 如果用户输入的是:")(cn=*)|(cn=*)|(cn=",就会将过滤器篡改为:&(cn="")(cn=*)|(cn=*)|(cn=""),就可以使条件总是为真。 是不是又和SQL注入有点像?
LDAP注入预防的主要措施也是编码,需要将特殊意义的字符编码,让过滤器认为它只是一个普通字符而不是特殊的分隔符,具体的特殊字符和编码方法如下:
字 符 | 转 义 |
* | \2a |
( | \28 |
) | \29 |
\ | \5C |
NUL | \00 |
编码方式是使用反斜杠(\)加上字符的十六进制数值。
关于LDAP的dn字段有一些特殊,因为这个字段的内容格式特殊,例如:一个DN由CN(A. James)、O(Test, Test2)以及C(AU)组成,表示为:CN=A. James,O=Test, Test2 ,C=AU。如果输入的部分含有都好, 等于号 = 就会篡改DN的内容,所以需要对\ , + “ < > ;这些字符进行特殊处理,处理的方式和上面的编码方式一样,是使用反斜杠(\)加上字符的十六进制数值。
如果有不妥之处,希望可以留言指出。谢谢!