浅谈二次反序列化利用
字数 1398 2025-08-10 17:51:51

二次反序列化利用技术详解

前言

二次反序列化是指在反序列化一个对象时,该对象中包含的某个字段本身又是一个可反序列化对象。这种技术常用于绕过黑名单等安全限制场景,在Java安全领域有重要应用。

三种二次反序列化利用方式

1. SignedObject方式

java.security.SignedObject类提供了标准的序列化/反序列化机制:

  • 构造方法中实现了序列化一个Serializable对象的操作,并将字节数组存储到content字段
  • SignedObject#getObject方法实现了将content字段反序列化的操作

利用原理:

  1. 将恶意序列化对象包装在SignedObject中
  2. 当SignedObject被反序列化时,黑名单检查会通过
  3. SignedObject的getObject方法被调用时,内部存储的恶意对象被二次反序列化

2. RMIConnector方式

javax.management.remote.rmi.RMIConnector类中的利用链:

  1. findRMIServerJRMP方法中对base64字符串进行反序列化
  2. findRMIServer方法调用findRMIServerJRMP,要求path以"/stub/"开头
  3. 通过反射修改urlPath属性为"/stub/base64_ser_str"形式
  4. 使用CC链中的InvokerTransformer#transform触发RMIConnector#connect

示例利用链:

InvokerTransform#transform 
-> RMIConnector#connect 
-> RMIConnector#findRMIServerJRMP

3. WrapperConnectionPoolDataSource方式

利用com.mchange.v2.c3p0.WrapperConnectionPoolDataSource

  1. 构造方法调用C3P0ImplUtils.parseUserOverridesAsString
  2. parseUserOverridesAsString处理hex字符串并最终调用反序列化
  3. 通过FastJson等注入点设置userOverridesAsString为恶意hex序列化数据

组合利用:

FastJson + CC6 + C3P0

HDCTF-二次反序列化利用实战

环境分析

  • 使用自定义的MyownObjectInputStream代替标准反序列化
  • 实现了黑名单机制,过滤危险类如TemplatesImpl
  • 重写了resolveClass方法进行安全检查

绕过思路

  1. 使用ROME反序列化链(利用EqualsBeanToStringBean
  2. 通过SignedObject包装恶意对象绕过黑名单
  3. ROME链会自动调用getObject方法触发二次反序列化

关键代码实现

// 创建恶意TemplatesImpl对象
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{bytes});
setFieldValue(obj, "_name", "Poria");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

// 使用ROME链构造初始payload
HashMap payload2 = getPayload(Templates.class, obj);

// 使用SignedObject进行二次包装
SignedObject signedObject = signedObject(payload2);

// 再次使用ROME链构造最终payload
HashMap payload = getPayload(SignedObject.class, signedObject);

绕过原理

  1. 外层反序列化时只看到SignedObject类,通过黑名单检查
  2. ROME链自动调用getObject方法
  3. getObject内部反序列化原始恶意对象(TemplatesImpl等)
  4. 此时已绕过外层安全检查,成功执行恶意代码

技术总结

  1. 黑名单绕过:二次反序列化能有效绕过基于类名的黑名单防御
  2. 利用场景:多出现在CTF比赛,实际环境中较少但仍有参考价值
  3. 防御建议
    • 使用白名单而非黑名单
    • 禁止反序列化不可信数据
    • 监控可疑的反序列化操作

参考资源

二次反序列化利用技术详解 前言 二次反序列化是指在反序列化一个对象时,该对象中包含的某个字段本身又是一个可反序列化对象。这种技术常用于绕过黑名单等安全限制场景,在Java安全领域有重要应用。 三种二次反序列化利用方式 1. SignedObject方式 java.security.SignedObject 类提供了标准的序列化/反序列化机制: 构造方法中实现了序列化一个Serializable对象的操作,并将字节数组存储到content字段 SignedObject#getObject 方法实现了将content字段反序列化的操作 利用原理: 将恶意序列化对象包装在SignedObject中 当SignedObject被反序列化时,黑名单检查会通过 SignedObject的getObject方法被调用时,内部存储的恶意对象被二次反序列化 2. RMIConnector方式 javax.management.remote.rmi.RMIConnector 类中的利用链: findRMIServerJRMP 方法中对base64字符串进行反序列化 findRMIServer 方法调用findRMIServerJRMP,要求path以"/stub/"开头 通过反射修改urlPath属性为"/stub/base64_ ser_ str"形式 使用CC链中的 InvokerTransformer#transform 触发 RMIConnector#connect 示例利用链: 3. WrapperConnectionPoolDataSource方式 利用 com.mchange.v2.c3p0.WrapperConnectionPoolDataSource : 构造方法调用 C3P0ImplUtils.parseUserOverridesAsString parseUserOverridesAsString 处理hex字符串并最终调用反序列化 通过FastJson等注入点设置 userOverridesAsString 为恶意hex序列化数据 组合利用: HDCTF-二次反序列化利用实战 环境分析 使用自定义的 MyownObjectInputStream 代替标准反序列化 实现了黑名单机制,过滤危险类如 TemplatesImpl 等 重写了 resolveClass 方法进行安全检查 绕过思路 使用ROME反序列化链(利用 EqualsBean 和 ToStringBean ) 通过 SignedObject 包装恶意对象绕过黑名单 ROME链会自动调用 getObject 方法触发二次反序列化 关键代码实现 绕过原理 外层反序列化时只看到 SignedObject 类,通过黑名单检查 ROME链自动调用 getObject 方法 getObject 内部反序列化原始恶意对象(TemplatesImpl等) 此时已绕过外层安全检查,成功执行恶意代码 技术总结 黑名单绕过 :二次反序列化能有效绕过基于类名的黑名单防御 利用场景 :多出现在CTF比赛,实际环境中较少但仍有参考价值 防御建议 : 使用白名单而非黑名单 禁止反序列化不可信数据 监控可疑的反序列化操作 参考资源 HDCTF2023 Web题出题记录 Java安全编码规范 反序列化漏洞防御指南