修 log4j 漏洞后感,请大佬解惑

2021-12-11 21:28:34 +08:00
 fighterhit

昨天在修 log4j 漏洞突然有一点疑问,请各位大佬解惑: 首先自己的服务是 maven 和 spring-boot 构建的,昨天先用 mvn dependency:tree -Dincludes=log4j 排查了自己的微服务 A 用的 log4j 2.11 是在第三方包 elasticsearch-6.43 下面,然后根据以往经验,就在自己的 A 服务的 pom.xml 中显示添加 log4j 2.15.0 版本,之前自己服务的 pom 是没有显示声明的,重新打包构建 mvn package。打好包 A.jar 后又将其解压看了下 BOOT-INFO/lib 下面 log4j 相关包都是 2.15.0 了,然后我又解压同目录下的 elasticsearch-6.43.jar 包,下面都是 classes 文件。一开始感觉很理所当然,但突然有几个问题:

  1. 显式的在自己服务的 pom 文件声明使用的依赖包比如 log4j 一定会覆盖下层第三方包依赖的 log4j 吗?这是由 maven 的什么机制决定的?
  2. 虽然自己的 A 服务用 pom 里声明的 log4j 2.15 版本构建出来 jar 包,也就是 classes 文件(我理解为二进制),但它依赖的 elasticsearch-6.43 jar 包 classes 不是已经是根据老版本的 log4j 2.11 构建出来的吗?所以 elasticsearch 这个 jar 包不是还是有问题,还是没有根本解决项目的 log4j 的漏洞问题?难道说 java 的 classes 文件是像动态链接库一样,运行时 elasticsearch-6.43 jar 会调用 2.15 的 log4j jar 包?这是 Java 的什么机制呢?
4789 次点击
所在节点    Java
31 条回复
zzyyqq
2021-12-11 21:31:50 +08:00
虽然我不是做后台的。 但是很理解你的感受。
有时候这些底层逻辑文档有点不太清楚。 自己得花好长时间走好多弯路才能研究透。
freeing
2021-12-11 21:36:44 +08:00
liprais
2021-12-11 21:42:17 +08:00
classloader 看命呗
你应该 exclude 掉别的 log4j
ikas
2021-12-11 21:46:36 +08:00
maven 有一套依赖版本处理方法,这个不重复,搜下就有很多

你的 pom deps 加了 log4j 2.15.0 ,elasticsearch (依赖 log4j 2.11 )..maven 经过计算..选择 log4j 版本是 2.15.0,那么最终你打包就是 log4j 2.15.0,也就是说 elasticsearch 就是调用 log4j 2.15.0.

这并不是什么 Java 机制..就是暴力直接替换...所以当 api 变化大时,会导致出现各种问题...

所以 maven 配置的本来就不是无脑随意配置...
codebigbang
2021-12-11 21:47:12 +08:00
关于第二点,我的理解不是 java 的机制,而是 spring 的容器化,把所有的对象都注册到了 spring 容器里,然后按需调用。申明的版本只是区别你组件的本身,但是调用对象还是根据 artifaceid 及类的具体名称来定位的,而不是 pom 里面的 version 。
你写代码的时候,都是写 com.demo.application.Test ,不需要区分版本,既然你引入了最新的,其他有使用了的肯定都使用最新的。
fighterhit
2021-12-11 21:49:48 +08:00
@zzyyqq 是的,之前感觉比较自然的事情突然有点想不通了
fighterhit
2021-12-11 21:50:10 +08:00
@freeing 谢谢,请问能解答下第二点吗?
fighterhit
2021-12-11 21:50:30 +08:00
@liprais 不 exclude 的话还会有问题?
fighterhit
2021-12-11 21:55:39 +08:00
@ikas 谢谢解答,但是 elasticsearch 这个 jar 包不是从 maven 中央仓库下好的官方用 log4j 2.11 打好的 jar 包吗?它的 classes 文件是不是已经把 log4j 2.11 的东西“揉进去”了(原谅我这种不太恰当的表达)?还是说 elasticsearch 的 classes 文件只是填充了 log4j 的函数接口名字什么的,没有规定版本,具体“链接”的时候再去找同目录下面具体版本的 log4j jar 包的 classes 文件?
ikas
2021-12-11 21:55:41 +08:00
当你处理所有依赖时,如果发现有重复的依赖,最好的方案就是 exclude,然后在自己项目 pom 明确声明这些依赖的版本..

要不然就是查看最终依赖 tree,观察是否都是自己想要的版本..

你说的第二点.他就是 maven 算出来最终一个版本,然后就打包了..maven 不会关心 elasticsearch 你用新版的 log4j 会不会出问题..
freeing
2021-12-11 21:55:47 +08:00
@fighterhit 你看看你最终的包里面的 lib 包有什么就知道了,根本没有 2.11 的 jar 包,只剩 2.15 的了
fighterhit
2021-12-11 21:57:08 +08:00
@freeing 谢谢,这个我理解的。但是 elasticsearch 这个 jar 包不是从 maven 中央仓库下好的官方用 log4j 2.11 打好的 jar 包吗?它的 classes 文件不是已经把 log4j 2.11 的东西“揉进去”了(原谅我这种不太恰当的表达)?还是说 elasticsearch 的 classes 文件只是填充了 log4j 的函数接口名字什么的,没有规定版本,具体“链接”的时候再去找同目录下面具体版本的 log4j jar 包的 classes 文件?
silerLee
2021-12-11 21:57:51 +08:00
第一个问题:pom 文件是继承的.这是一个优先级的问题只会取一个版本,类似于子类重写了父类的实现.优先使用你的项目的 pom 的版本指定的依赖.一定会覆盖下层第三方包依赖因为你在本地显示声明了.

第二个问题 classes 文件并不是二进制只是字节码.jar 包的加载过程是去加载器中查找依赖的包.那么你的 pom 已经定义了新的包只会使用哪个版本的包.这就是为什么安全升级有时候你发现升级的版本不兼容过新.因为这个构建是不知道版本的它只认完整的包名+类名,你不声明版本.它自带的 pom 会引入依赖.你声明了就会使用你显示声明的版本的包. 建议看下 JVM 加载 jar 的流程.

如何去验证?
你完全可以排掉依赖的包.加载的时候就会报错 notfoundclass.
ikas
2021-12-11 22:00:22 +08:00
@fighterhit 这么说吧..java 不存在什么链接...
在 elasticsearch 自己编译时,他依赖的是 log4j 2.11...然后用到了 2.11 种的各种类.接口等等...当编译完成时.实际 elasticsearch 种不会存在任何 log4j 2.11 的文件等等...

当你自己项目用了一个高版本的 log4j..那么 elasticsearch 运行就是直接调用这个高版本


==========
当然这里说的都是常规的..java 可以内部直接包含依赖,然后不暴露出来,比如 java module
fighterhit
2021-12-11 22:00:23 +08:00
@codebigbang 喔,相当于运行时代码会根据类名去调用目录下面同名的 jar 包,感觉也就像运行期动态链接一样,maven 只是简单的把包放在了那里仅此而已?
ikas
2021-12-11 22:02:59 +08:00
@fighterhit 其实这就是 class 与 classloader 的内容了....学下就知道了
yangyaofei
2021-12-11 22:04:29 +08:00
应该是调用包的时候,调用的地方其实只有一个指针(package 的全路径)指向要访问调用的代码,有没有是加载起来的, 应该同样的 package 都是一样的
fighterhit
2021-12-11 22:06:42 +08:00
@ikas 好的,谢谢大佬!
fighterhit
2021-12-11 22:10:50 +08:00
@silerLee 谢谢解答。昨天修完就在想如果把 log4j 降到一个很低且不兼容 elasticsearch 的版本应该就会报错,大佬这么说感觉应该就是这样,我去补一下加载这块。
fighterhit
2021-12-11 22:11:33 +08:00
@yangyaofei 嗯谢谢解答,我感性理解也是这样

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/821572

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX