2023年6月21日发(作者:)
【LDAP】LDAP注⼊漏洞与防御0x01 前⾔前两天爆了⼀个LDAP漏洞,据说存在了8年现在才被发现,感概⼀下,不知这8年来有多少站被搞了。。。想着复现这个漏洞,就先复习⼀下LDAP注⼊的相关知识吧,差了很多资料,记⼀下笔记。0x02 LDAP介绍在学习LDAP注⼊之前,⾸先要了解LDAP的运⾏机制。什么是LDAP?LDAP(Lightweight Directory Access Protocol):轻量级⽬录访问协议,是⼀种在线⽬录访问协议。LDAP主要⽤于⽬录中资源的搜索和查询,是X.500的⼀种简便的实现。简单来说,可以理解为LDAP是某种搜索协议,就像我们熟知的数据库⼀样,我们利⽤SQL语句进⾏查询数据库中的数据。⽽LDAP也有⼀套⾃⼰的查询语句,来进⾏查询。LDAP查询语法search语法:attribute operator valuesearch filter options:( "&" or "|" (filter1) (filter2) (filter3) ...) ("!" (filter))LDAP的搜索语法其实很容易,这⾥看不明⽩的话,往下看⼀下具体实例就会明⽩的。0x03 LDAP注⼊攻击轻量级⽬录访问协议是通过TCP/IP查询和修改⽬录服务的协议,使⽤最⼴泛的LDAP服务如微软的ADAM(Active Directory ApplicationMode)和OpenLDAP。(&(attribute=value)(injected_filter)) (second_filter)需要注意的是,在OpenLDAP中,第⼆个过滤器会被忽略,只有第⼀个会被执⾏,那么类似上⾯的这种注⼊就可以成功的。⽽在ADAM中,有两个过滤器的查询是不被允许的,那么这种注⼊是没什么⽤的。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*))0x04 LDAP注⼊防御LDAP注⼊的防御跟SQL注⼊的防御其实差不多,主要就是要把⽤户输⼊的东西过滤好,基本就可以防御了。下图包含了LDAP中⽤到的特殊字符和需要转义处理的字符:左边的字符在正常情况下是不会⽤到的,如果在⽤户的输⼊中出现了需要⽤反斜杠转义处理。⽽右边的圆括号这些如果不过滤的话就会导致过滤器闭合⽽⽣产攻击者需要的filter,这⾥看到不仅是⽤反斜杠处理,还将字符变成了相应的ASCII码值,这些符号本不该出现。这段php防御代码可以记录⼀下:function ldapspecialchars($string) { $sanitized=array('' => '5c', '*' => '2a', '(' => '28', ')' => '29', " 00" => '00'); return str_replace(array_keys($sanitized),array_values($sanitized),$string);}LDAP服务开启的端⼝是389,如果发现某个服务器上开启了该端⼝很可能就是开启了LDAP服务0x05 参考⽂献
2023年6月21日发(作者:)
【LDAP】LDAP注⼊漏洞与防御0x01 前⾔前两天爆了⼀个LDAP漏洞,据说存在了8年现在才被发现,感概⼀下,不知这8年来有多少站被搞了。。。想着复现这个漏洞,就先复习⼀下LDAP注⼊的相关知识吧,差了很多资料,记⼀下笔记。0x02 LDAP介绍在学习LDAP注⼊之前,⾸先要了解LDAP的运⾏机制。什么是LDAP?LDAP(Lightweight Directory Access Protocol):轻量级⽬录访问协议,是⼀种在线⽬录访问协议。LDAP主要⽤于⽬录中资源的搜索和查询,是X.500的⼀种简便的实现。简单来说,可以理解为LDAP是某种搜索协议,就像我们熟知的数据库⼀样,我们利⽤SQL语句进⾏查询数据库中的数据。⽽LDAP也有⼀套⾃⼰的查询语句,来进⾏查询。LDAP查询语法search语法:attribute operator valuesearch filter options:( "&" or "|" (filter1) (filter2) (filter3) ...) ("!" (filter))LDAP的搜索语法其实很容易,这⾥看不明⽩的话,往下看⼀下具体实例就会明⽩的。0x03 LDAP注⼊攻击轻量级⽬录访问协议是通过TCP/IP查询和修改⽬录服务的协议,使⽤最⼴泛的LDAP服务如微软的ADAM(Active Directory ApplicationMode)和OpenLDAP。(&(attribute=value)(injected_filter)) (second_filter)需要注意的是,在OpenLDAP中,第⼆个过滤器会被忽略,只有第⼀个会被执⾏,那么类似上⾯的这种注⼊就可以成功的。⽽在ADAM中,有两个过滤器的查询是不被允许的,那么这种注⼊是没什么⽤的。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*))0x04 LDAP注⼊防御LDAP注⼊的防御跟SQL注⼊的防御其实差不多,主要就是要把⽤户输⼊的东西过滤好,基本就可以防御了。下图包含了LDAP中⽤到的特殊字符和需要转义处理的字符:左边的字符在正常情况下是不会⽤到的,如果在⽤户的输⼊中出现了需要⽤反斜杠转义处理。⽽右边的圆括号这些如果不过滤的话就会导致过滤器闭合⽽⽣产攻击者需要的filter,这⾥看到不仅是⽤反斜杠处理,还将字符变成了相应的ASCII码值,这些符号本不该出现。这段php防御代码可以记录⼀下:function ldapspecialchars($string) { $sanitized=array('' => '5c', '*' => '2a', '(' => '28', ')' => '29', " 00" => '00'); return str_replace(array_keys($sanitized),array_values($sanitized),$string);}LDAP服务开启的端⼝是389,如果发现某个服务器上开启了该端⼝很可能就是开启了LDAP服务0x05 参考⽂献
发布评论