博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Java编码指南:编写安全可靠程序的75条建议》—— 指南9:防止LDAP注入
阅读量:6078 次
发布时间:2019-06-20

本文共 3506 字,大约阅读时间需要 11 分钟。

本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.9节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F.Sutherland(迪恩 F.萨瑟兰), David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

指南9:防止LDAP注入

轻量级目录访问协议(Lightweight Directory Access Protocol,LDAP)允许应用程序执行远程操作,如在目录中搜索和修改记录。不足的输入处理(sanitization)和验证会导致LDAP注入攻击,并允许恶意用户通过使用目录服务来收集被限制的信息。

白名单可以用来限制用户输入,使其符合一个有效的字符列表。禁止加入白名单的字符或字符序列包括:Java命名和目录接口(Java Naming and Directory Interface,JNDI)的元字符和LDAP特殊字符,这些字符都列在了表1-1中。

116de4cd03c9c130be81ee76a1263d6b8e3241a1

注:*这是一个字符序列。

LDAP注入示例

试想一个LDAP数据交换格式(LDAP Data Interchange Format,LDIF)文件,其中包含的记录格式如下:

dn: dc=example,dc=comobjectclass: dcobjectobjectClass: organizationo: Some Namedc: exampledn: ou=People,dc=example,dc=comou: PeopleobjectClass: dcobjectobjectClass: organizationalUnitdc: exampledn: cn=Manager,ou=People,dc=example,dc=comcn: Managersn: John Watson# Several objectClass definitions here (omitted)userPassword: secret1mail: john@holmesassociates.comdn: cn=Senior Manager,ou=People,dc=example,dc=comcn: Senior Managersn: Sherlock Holmes# Several objectClass definitions here (omitted)userPassword: secret2mail: sherlock@holmesassociates.com

并且对有效用户名和密码的搜索经常使用下面这种形式:

(&(sn=
)(userPassword=
))

然而,攻击者可以通过在USERSN字段中输入S、在USERPASSWORD字段中输入来绕过身份验证。这样的输入将会使所有在USERSN字段中以S开头的记录被悉数查出。

如果验证例程存在LDAP注入风险,就会导致未经验证的用户登录。同样地,有类似问题的搜索例程就会将该目录下部分甚至全部数据暴露给攻击者。

违规代码示例

下面的违规代码示例使用LDAP协议来允许调用者通过searchRecord()方法来搜索目录中的记录。匹配到调用者提供的用户名和密码后,字符串过滤器将会从结果集中过滤出匹配的结果。

// String userSN = "S*"; // Invalid// String userPassword = "*"; // Invalidpublic class LDAPInjection { private void searchRecord(String userSN, String userPassword)   throws NamingException {  Hashtable
env =   new Hashtable
();  env.put(Context.INITIAL_CONTEXT_FACTORY,      "com.sun.jndi.ldap.LdapCtxFactory");  try {   DirContext dctx = new InitialDirContext(env);   SearchControls sc = new SearchControls();   String[] attributeFilter = {"cn", "mail"};   sc.setReturningAttributes(attributeFilter);   sc.setSearchScope(SearchControls.SUBTREE_SCOPE);   String base = "dc=example,dc=com";   // The following resolves to (&(sn=S*)(userPassword=*))   String filter = "(&(sn=" + userSN + ")(userPassword=" +           userPassword + "))";   NamingEnumeration
results =    dctx.search(base, filter, sc);   while (results.hasMore()) {    SearchResult sr = (SearchResult) results.next();    Attributes attrs = (Attributes) sr.getAttributes();    Attribute attr = (Attribute) attrs.get("cn");    System.out.println(attr);    attr = (Attribute) attrs.get("mail");    System.out.println(attr);   }   dctx.close();  } catch (NamingException e) {   // Forward to handler  } }}

当恶意用户输入别有用心的值时,正如前面提到的,这个基本的身份验证方案没能对需要用户访问特权的信息查询作出限制。

合规解决方案

下面的合规解决方案使用白名单对用户输入进行无害化处理,使得filter字符串只包含有效字符。在这段代码中,userSN只可能包含字母和空格,而密码则只可能包含字母数字字符。

// String userSN = "Sherlock Holmes"; // Valid// String userPassword = "secret2"; // Valid// ... beginning of LDAPInjection.searchRecord() ...sc.setSearchScope(SearchControls.SUBTREE_SCOPE);String base = "dc=example,dc=com";if (!userSN.matches("[\\w\\s]*") ||  !userPassword.matches("[\\w]*")) { throw new IllegalArgumentException("Invalid input");}String filter = "(&(sn = " + userSN + ")(userPassword=" +        userPassword + "))";// ... remainder of LDAPInjection.searchRecord() ...

当密码这样的数据库字段必须包含特殊字符时,至关重要的是,确保可信的数据以无害的形式存储在数据库中,并且在验证或比较用户输入前必须对其进行标准化。在缺乏广泛的标准化和白名单过滤的情况下,使用在JNDI和LDAP中有特殊含义字符的程序是极不安全的。特殊字符在被添加到白名单验证之前必须被转换为清洁的安全值。就像用户输入在被验证之前首先要被标准化一样。

适用性

未能对不可信输入做无害化处理可能导致信息泄露和特权升级。

转载地址:http://fzogx.baihongyu.com/

你可能感兴趣的文章
Dapper丶DapperExtention,以及AbpDapper之间的关系,
查看>>
搞IT的同学们,你们在哪个等级__那些年发过的帖子
查看>>
且谈语音搜索
查看>>
MySQL数据库导入导出常用命令
查看>>
低版本Samba无法挂载
查看>>
Telegraf+Influxdb+Grafana构建监控平台
查看>>
使用excel 展现数据库内容
查看>>
C#方法拓展
查看>>
MySql.Data.dll的版本
查看>>
Linux系统磁盘管理
查看>>
hdu 2191 (多重背包+二进制优化)
查看>>
home.php
查看>>
neo4j---删除关系和节点
查看>>
redis分布式锁redisson
查看>>
什么样的企业可以称之为初创企业?
查看>>
Python爬虫之BeautifulSoup
查看>>
《HTML 5与CSS 3权威指南(第3版·下册)》——第20章 使用选择器在页面中插入内容...
查看>>
如何判断自己适不适合做程序员?这几个特点了解一下
查看>>
newinstance()和new有什么区别
查看>>
android下载封装类
查看>>