在网上的问题栏目有小伙伴在问为什么Log4J要提供对JNDI的支持,默认支持这种小众特性,反而导致了问题,是造成全网程序员加班修复漏洞的罪魁祸首,看到这个问题下各种吐槽JNDI,JNDI太冤了,我想为它正名下,其实JNDI在大型项目中广泛使用,请看下文。
那么,JNDI真的是罪魁祸首吗?JNDI是干什么?
听我道来。
此次漏洞的锅并不能扣在JNDI上,它只是定义了一套规范,具体实现是各个厂商实现的。
JNDI最最核心的目的:是为了解耦!是为了开发出更加可维护、可扩展的系统。它不是一个小众特性,很有历史渊源,是当年Sun制定的规范。
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver", true, Thread.currentThread().getContextClassLoader());
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?user=username&password=password");
......
conn.close();
} catch(Exception e) {
e.printStackTrace();
} finally {
if(conn!=null) {
try {
conn.close();
} catch(SQLException e) {}
}
}
解决办法:
程序员应该不需要关心“具体的数据库是什么?“、“JDBC驱动程序是什么?”、“JDBC URL格式是什么?”、“访问数据库的用户名和口令是什么?”、“连接池参数是什么?”等等这些问题,程序员编写的程序应该没有对 JDBC 驱动程序的引用,没有服务器名称,没有用户名称或口令,甚至没有数据库池或连接管理。而是把这些问题交给J2EE容器来配置和管理,程序员只需要对这些配置和管理进行引用即可。
dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/testDB");
JNDI在中间件中大量使用,由于互联网企业中间件用得少,导致不少小伙伴对JNDI很陌生。
中间件现在用得最多的是JBOSS的WebLogic和IBM的WebSphere,这些中间件中大量使用了JNDI,用JNDI不光是为了解耦,还有是为了安全,开发人员不需要接触密码等敏感信息,只需要知道JNDI名就行了。
可能有小伙伴问WebLogic、WebSphere是什么,用的多吗,这些中间件主要用在大型集团、金融、银行、保险等行业,这些企业注重服务的稳定性可靠性以及相关的技术服务,这几年热门的互联网行业用的比较少,一般用免费的tomcat。
然后选择WEB应用下的Web-INF文件夹下的web.xml,在其中添加JNDI名字,如下图:
最后将Web应用部署到WebSphere服务器上。
代码当中你只需要知道JNDI名字就可以获取到datasource,而无需关心数据库的URL、用户名、密码等信息:
dataSource = (DataSource) ctx.lookup("jdbc/TestDB");
说了这么多,又是JDBC,又是WebSphere的,你会说这跟Log4J有什么关系,其实他们的原理是一模一样的,Log4J也是用了JNDI的lookup去查找资源,比如下面的代码,Log4J发现打印的字符串中有${,并且里面是JNDI资源,就会发起请求(lookup)加载资源,但由于Log4J旧版本有漏洞,导致了远程代码执行漏洞。
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test {
private static final Logger logger = LogManager.getLogger(Test.class);
public static void main(String[] args) {
String str = "${jndi:ldap://127.0.0.1:1234/evil}";
logger.error("params:{}",str);
}
}
至此,你是否掌握了JNDI知识了呢,它的设计思路其实蛮好的,只不过Log4J2没有掌握好,产生了漏洞。
最后,总结下:
JNDI 就是一个别名,为每个资源取一个别名,不需要知道这个别名背后的配置细节是什么,说白了就是解耦,符合依赖倒置设计原则。
在J2EE中,JNDI 是把J2EE应用程序合在一起的粘合剂,JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。
最后的最后,对JNDI归纳如下:
1、JNDI 提出的目的是为了解耦,是为了开发更加容易维护,容易扩展,容易部署的应用。
2、JNDI 是一个Sun提出的一个规范(类似于JDBC),具体的实现是各个厂商实现的,可以看出,老外还是非常认可这个规范,很多地方做了很多解耦的设计,包括Log4J。
3、JNDI 在J2EE系统中的角色是“交换机”,是J2EE组件在运行时间接地查找其他组件、资源或服务的通用机制。
4、JNDI 是通过资源的名字来查找的,资源的名字在整个J2EE应用中是唯一的。
推荐文章:
关注研磨架构,回复面试,领取大厂面经资料。
关注研磨架构,回复log,获取最新Log4J远程代码执行漏洞解决方案。
我的微信:
原文始发于微信公众号(研磨架构):引发Log4J2远程代码执行漏洞的JNDI到底是啥?
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论