这个应该是技术人最近谈的比较多的话题了,有的公司连夜在修复,这个时候也体现每家公司的工程化能力了,是一个个应用去发版,还是只要中间件层面动一动就可以看到各家公司的技术实力了。
这个话题网上已经有很多文章了,好多是讲原因的,我就不在这里重述了,这篇文章重点讲下识别和处理。
一、如何确定是否中招或已经修复
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
String cmdMessage = "${jndi:rmi://127.0.0.1:8081/ExportObject}";
logger.info("log4j2testinfo"+cmdMessage );
logger.error("log4j2testerror"+cmdMessage );
logger.warn("log4j2testwarn"+cmdMessage );
}
}
如果运行上面的代码之后报错误有什么lookup的错误,或者有监听了8081端口,则说明你的系统中招了,或者还没修复完毕;
二、查看依赖的库是否如何引用的
查看依赖树,看是否有相关库,具体运行如下命令:
mvn dependency:tree
如果有以下的库则要注意版本了,如果版本在2.x到2.15.0-rc1之间则要及时修复;
注意类的全名开头是org.apache.logging,如果直接是log4j的则不影响:
三、解决方案
1、找到相应的依赖jar包,引入的时候排除掉
<dependency>
<groupId>com.xx.framework</groupId>
<artifactId>xx-log4j2-starter</artifactId>
<exclusions>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
项目中用的比较多的是下面几个包:
log4j-api
log4j-core
log4j-jul
log4j-slf4j-impl
2、手动引入相关依赖包
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.15.0-RC2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.15.0-RC2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.15.0-RC2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-jul</artifactId>
<version>2.15.0-RC2</version>
</dependency>
还有一种办法,就是修改相关参数,jvm启动参数增加
-Dlog4j2.formatMsgNoLookups=true
这个是偷懒的办法,即不升级jar包的情况下修改参数,而禁用相关功能,这个作为临时的方案,不建议在生产上长期使用;
四、总结
解决方案主要是升级相关jar包,当然可以临时关闭下相关功能然后再升级;
Java中有很多功能比较强大的反射API,允许直接编译Java代码,这些是双刃剑,用的不好就容易中招,所以针对这个API如果处理的参数有用户输入的就特别需要注意,就像Fastjson一样,性能是强了,但也很容易被黑客利用,因此在程序中对所有输入参数做好安全处理,建议通过拦截器等方式在请求进来的时候做统一处理,这样后续有需求也方便统一处理。