Nevado JMS反序列化审计tips

http://nevado.skyscreamer.org/

Nevado JMS 是 Amazon SQS 的 JMS 驱动程序

流程分析

按照文档写一个消息接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class App {
public static void main(String[] args) throws Exception {
new ClassPathXmlApplicationContext("applicationContext.xml");
NevadoConnectionFactory connectionFactory = new NevadoConnectionFactory();
NevadoConnection connection = connectionFactory.createConnection();
NevadoSession session = connection.createSession(false, NevadoSession.AUTO_ACKNOWLEDGE);
NevadoQueue queue = session.createQueue("test");
NevadoMessageConsumer consumer = session.createConsumer(queue);
NevadoMessage message = consumer.receive();
// if (message instanceof TextMessage) {
// TextMessage textMessage = (TextMessage) message;
// System.out.println("Received message: " + textMessage.getText());
// }
connection.close();
}
}

在上面的流程中,会创建一个test队列传到receive方法,具体为:

队列“test”传进createConsumer方法,在createConsumer方法时被传递进了NevadoMessageConsumer对象

image

在构造函数NevadoMessageConsumer中,因为传进的是queque类型,所以会进入else,此时_destination就是队列test

image

回到消息接收中,receive()方法会监听队列,从队列中接收消息

image

继续跟进getUnfilteredMessage方法查看实现流程

image

getUnfilteredMessage方法是过滤被消费的消息,如果接收模式是2,就会先从缓存读取

image

当不满足条件时就会调用this._connection.getSQSConnector().receiveMessage来接收队列消息,然后再将被接收过的消息添加到缓存中

image

具体为:

已知初始化时_connection是NevadoConnection对象

image

image

getSQSConnector方法返回的是SQSConnector

image

image

这个接口封装了 Amazon SQS 相关的 API 调用,receiveMessage方法是接收消息

image

所以从代码分析,当不满足条件时,就会接收从Amazon SQS发送的队列消息

image

跟进实现receiveMessage方法的实现类

在receiveMessage方法中,会将取出的队列传进receiveSQSMessage方法进一步接收队列中的消息

image

跟进receiveSQSMessage方法

image

此时receiveSQSMessage方法返回的就是test里面的消息,返回receiveMessage

image

接收到队列消息后,将消息等参数传进convertSqsMessage方法

image

在convertSqsMessage方法中,会根据传进的destination类型来做不同的消息取出动作

image

随后将取出的消息传进deserializeMessage方法做反序列化

image

跟进deserializeFromString

image

在deserializeFromString方法中,会对传进的消息做一次base64解码操作,然后再使用Hessian2Input对象进行反序列化。

根据代码的流程,如果要进行漏洞利用,acknowledgeMode就必须不等于2且transacted是false才能进入else走到反序列化功能,如开头所写,NevadoSession的模式分为4种:

1
2
3
4
int AUTO_ACKNOWLEDGE = 1;
int CLIENT_ACKNOWLEDGE = 2;
int DUPS_OK_ACKNOWLEDGE = 3;
int SESSION_TRANSACTED = 0;

且因为反序列化使用的是Hessian2Input,所以得知序列化的数据得是Hessian格式

该组件提供了一个反序列化工具类SerializeUtil.class,可以直接用来序列化恶意数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String serializeToString(Serializable serializable) throws IOException {
byte[] data = serialize(serializable);
return new String(Base64.encodeBase64(data));
}

public static byte[] serialize(Serializable serializable) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Hessian2Output hessian2Output = new Hessian2Output(byteArrayOutputStream);
hessian2Output.setSerializerFactory(new SerializerFactory(SerializeUtil.class.getClassLoader()));
hessian2Output.startMessage();
if (serializable instanceof Character) {
serializable = new CharWrapper((Character)serializable);
}

hessian2Output.writeObject(serializable);
hessian2Output.completeMessage();
hessian2Output.close();

漏洞验证:

方式一、本地部署验证

发送消息的客户端,destination类型是queque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Appclient {
public static void main(String[] args) throws JMSException {
new ClassPathXmlApplicationContext("applicationContext.xml");
NevadoConnectionFactory connectionFactory = new NevadoConnectionFactory();
NevadoConnection connection = connectionFactory.createConnection();
//false和1
NevadoSession session = connection.createSession(false, NevadoSession.AUTO_ACKNOWLEDGE);
NevadoQueue queue = session.createQueue("test");
NevadoMessageProducer producer = session.createProducer(queue);
//如果destination类型是topic,那就是{"Message":"base64编码后的恶意数据"}
NevadoMessage message = session.createTextMessage("base64编码后的恶意数据");
producer.send(message);
connection.close();

}

接收消息:

image

方式二、搭配amazon sqs使用验证(没用过,理论是这样)

注册一个amazon,使用sqs服务

image

然后发送消息

image

或者

image

集群在接收消息后就会触发

结尾

在跟进的时候还发现了亚马逊接收消息有一个getObject,应该也是个反序列化的点,后来搜网上有文章,属于是nday这里就不继续说了

Maven依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.31</version>
</dependency>
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>nevado-jms</artifactId>
<version>1.3.2</version>
</dependency>

 




声明:
本文章用于学习交流,严禁用于非法操作,出现后果一切自行承担,阅读此文章表示你已同意本声明。

Disclaimer:
This article is for study and communication. It is strictly forbidden to use it for illegal operations. All consequences shall be borne by yourself. Reading this article means that you have agreed to this statement.