ActiveMQ CNVD-2023-69477

ActiveMQ Intro

ActiveMQ是一个消息队列,消息队列是在消息的传输过程中保存消息的容器,提供不同进程或同一进程不同线程之间的通讯方式,基于JMS规范(JMS:Java Message Service Java消息服务,有一套API接口)

其他类似的消息中间件:RabbitMQ、Kafka、RocketMQ、ZeroMQ

消息中间件的作用主要有3点

  • 异步性提升性能(放入消息队列,不需要立即处理)

  • 降低耦合度

  • 流量削峰(消息中间件起到了缓冲的作用)

image-20231221211113882
  • producer:消息生产者

  • broker:消息处理中心,存储、确认、重试(broker可以翻译成代理)

  • consumer:消息消费者

ActiveMQ支持多种应用协议:OpenWire(常用)、StompREST、WSNotification、AMQP。

提供了两种消息模式:点对点模式(Queue)、发布订阅模式(Topic)

点对点模式中队列的消息只会被一个消费者所消费

image-20231221211128751

发布订阅模式中每个订阅者都会收到消息

image-20231221211138060

JMS定义的消息体类型有如下几种:

属性
类型

TextMessage

文本消息

MapMessage

k/v

BytesMessage

字节流

StreamMessage

java原始的数据流

ObjectMessage

序列化的java对象

Quick Start

windows下ActiveMQ下载👉https://activemq.apache.org/download-archives.html

这里下载5.18.2版本,/bin/win64目录下有一个activemq.bat,ActiveMQ默认端口为61616

ActiveMQ还提供了管理员控制台http://localhost:8161/admin/

默认账号密码admin/admin

Java引入依赖

Provider

Consumer

Consumer端成功打印文本消息

image-20231221211202611
image-20231221211207941

Analysis

漏洞版本:ActiveMQ < 5.18.3

攻击对象:ActiveMQ服务端

ExceptionResponseMarshallertightUnmarshallooseUnmarshal

image-20231221211218869
image-20231221211226719

会调用到父类的BaseDataStreamMarshallertightUnmarsalThrowablelooseUnmarsalThrowable

image-20231221211237104

分别反序列化类名和消息,接着调用createThrowable

image-20231221211246556

调用了类的构造方法,且构造方法只接收一个字符串

上面可知ActiveMQ的8161端口提供了一个管理员控制台,那就大概率依赖了Spring Web,看一下ActiveMQlib目录,果然有。

那就可以考虑调用org.springframework.context.support.ClassPathXmlApplicationContext的构造方法,远程加载恶意xml文件RCE。

ActiveMQ服务端接收到消息后,会调用org.apache.activemq.openwire.OpenWireFormat#unmarshal

unmarshal再到doUnmarshal,从数据流里读取数据类型,获取对应的序列化器,调用其tightUnmarshallooseUnmarshal

为接上面的sink点,我们这里需要获取到ExceptionResponseMarshaller

image-20231221211255861

对应的,客户端发送消息,会调用marshal,也是根据类型获取序列化器

image-20231221211305370

看看ExceptionResponseMarshaller#tightMarshal1 -> BaseDataStreamMarshaller#tightMarshalThrowable1

image-20231221211313621

这里获取了异常类的类名和消息(Throwable继承了其父类的message属性)

ExceptionResponseMarshaller即为ExceptionResponse的序列化器

image-20231221211322076

异常打印的消息来自于exception成员,所以ClassPathXmlApplicationContext需要继承Throwable

image-20231221211330866
image-20231221211351699

Patch

https://github.com/apache/activemq/compare/activemq-5.18.3...activemq-6.0.0

新版本BaseDataStreamMarshaller#createThrowable增加了一处判断

image-20231221211401700

OpenWireUtil#validateIsThrowable判断类是否为Throwable的子类,否则抛出异常

image-20231221211409230

Last updated

Was this helpful?