公司里大多数项目使用的都是log4j,但是使用的是较低的1.2+版本(够用即可,并且可能出于对log4j高版本稳定性的怀疑,果然不出所料),而我搭建的项目都是使用的性能更优、功能更全、稳定性更高的logback框架。本来以为本次漏洞与我们无关,万万没想到log4j2的漏洞警告还是降临到我们的每个项目上(WTF?)。
资安报告记录的问题点是项目中2+版本的log4j-api、log4j-to-slf4j依赖,两者是接口依赖,没有核心实现类log4j-core的问题。本次漏洞源头是2+~2.15.0-rc1的log4j-core中的lookup扩展的实现类 JndiLookup
的设计缺陷导致,前两者不影响,于是找到资安同事进行理论。最终,我们被资安同事以Boss不懂这些,Boss只想知道项目中不再包含问题版本的log4j相关组件说服。好吧,改。
于是发起对了上百个大小项目的log4j“讨伐”:
使用logback的项目亦遭到波及
虽然使用了logback,但要提防其他依赖包内嵌了log4j组件。这里主要问题是Spring Boot起步依赖中内嵌的log4j-api、log4j-to-slf4依赖版本的问题版本区间内。这里直接移除即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
通过这里查看依赖移除成功没(是否还包含该依赖):
至于其他依赖包内嵌的log4j组件,用同样的办法去除。使用intellj正式版的视图工具可以快速定位依赖关系。
使用log4j1.2+版本的项目
由于使用的是log4j,不能将log4j-api、log4j-to-slf4依赖简单粗暴地移除。这里直接显式指定版本即可,这里直接2.17.0版本:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.17.0</version>
</dependency>
具体依赖直接前往官网下载,不再啰嗦。
漏洞虽然很大,但解决只要更新或去除log4j依赖就行了
权宜之计
配置JVM参数将lookup功能关闭,自行百度。不过这只是权宜之计,问题依赖还在,最终还是要升级版本的。
题外话
一直有个疑问,开发者们为什么不使用logback取代log4j呢?
log4j从起源之初到现在受尽万千开发者宠爱,但是log4j从开发之初,到遭到log4j作者嫌弃而直接重构一套更优的logback,到现在爆出核弹级漏洞,到2.15.0-rc2漏洞修复,2.16.0版本爆出新的漏洞,再到2.17.0的最终版(不确定还有没新的漏洞),可见log4j还是不尽人意。
logback是采用多线程进行日志处理的,性能上肯定甩log4j几条街,并且支持日志自动切割,自动删除过期日志,功能上也比log4j强大。logback有漏洞吗?肯定有,像下面这个:
日志库logback的攻击路径_黑客技术gback.configurationFile 来获取配置文件的地址(支持远端 URL地址)。如果找不到,再去 classpath 下依次查找如下三个文件作为配置文件:a) logback-test.xml b) logback.groovy(最新版本似乎不再支持) c) logback.xml 获取配置文件之后,通过 JoranConfigurator.doConfigure() (实现在父类的GenericConfigurator.doConfigure()中) 读取 xml 配置文件,其中调用 SaxEventRecorder.recordEvents() 解析 xml 配置文件时存在 XXE 漏洞。动态加载通常情况下,配置文件的这一类 XXE 漏洞并不是大问题,毕竟配置文件只会在初始化的时候加载一次,攻击者没机会触发漏洞。但是 logback 库不一样。只要配置文件中配置了 日志库logback的攻击路径_记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华黑客技术http://www.hackdig.com/03/hack-71209.htm但是不启用 scan 参数就不影响,对比起log4j的大漏洞还是没啥的,稳定性也比log4j好。Spring Boot也集成了logback,但没有集成log4j(需要额外引入log4j依赖),便捷度也比log4j高。
那为什么不使用logback呢?年代很久远的项目好说,但是新项目呢?logback也已经出来很久了,所以性能更优、功能更强大、稳定性和便捷度更高的logback为什么没干过log4j呢?
分享一篇去年收藏的写的很有意思的关于log框架起源的文章:
PS:最后,还是要对log4j的开源维护者表示敬佩,没有工资,出了漏洞还要背锅,忍受骂声一片,然依旧推动log4j不断前行。可能log4j不倒就是因为他们吧,膜拜。