Java序列化基础-URLDNS利用
字数 1584 2025-08-19 12:42:34
Java反序列化漏洞基础与URLDNS利用链分析
0x01 序列化基础概念
序列化定义
序列化是指将一个对象转换为字节序列的过程,包含:
- 对象的数据
- 对象的类型
- 对象中存储的属性等信息
Java序列化实现
- 通过实现
java.io.Serializable接口 - 只有实现了
Serializable接口的对象才能被序列化 - 注意:序列化的是对象而不是类
序列化限制
- 静态属性不能序列化
- 原因:静态变量属于类,在类加载时获取内存空间存储在静态区
- 访问方式:应直接通过类名访问而非对象引用
- Transient瞬态属性不能序列化
序列化用途
- 数据持久化:将数据永久保存在硬盘上
- 通过输出流将内存中的数据保存在文件中
- 远程通信:在网络上传送对象的字节序列
反序列化
- 序列化的逆过程,将字节流转换回对象
- 过程:开启输入流通道,Java从字节流中的信息重构对象并重新加载到内存
0x02 反序列化漏洞原理
漏洞产生原因
- 服务端反序列化数据时,客户端传递类的
readObject方法中的代码会自动执行 - 本质:攻击者利用服务器反序列化过程执行恶意代码
反序列化利用形式
- 入口类的
readObject直接调用危险方法(不常见) - 入口类参数中包含可控类,该可控类有危险方法,被反序列化时被
readObject调用(不常见) - 入口参数中包含可控类,该可控类调用其他含有危险方法的类(常见)
- 构造函数/静态代码块等类加载时隐式执行
利用前提
- 利用链里的类必须继承
Serializable - 危险方法通常不是指可控类本身的方法,而是指与可控类方法同名且类型相同的函数
0x03 URLDNS利用链分析
URLDNS链特点
- 学习Java反序列化的第一条Gadget Chain
- 只能发起DNS请求,不能进行其他利用
- 优点:
- 不限制JDK版本
- 使用Java内置类,无第三方依赖要求
- 目标无回显时,可通过DNS请求验证漏洞存在
原理分析
java.util.HashMap实现了Serializable接口,重写了readObject- 反序列化时会调用
hash函数计算key的hashCode java.net.URL实现了Serializable接口,其hashCode计算时会调用getHostAddress解析域名,从而发出DNS请求
利用目的
- 序列化时不请求DNS,反序列化时请求DNS
- 实现方式:
- 序列化时
hashCode值不等于-1(直接返回不进行DNS解析) - 反序列化时
hashCode值等于-1(触发DNS解析)
- 序列化时
Gadget Chain调用流程
HashMap.readObject()
--> HashMap.hash(URL)
--> URL.hashCode()的handler.hashCode(即URLStreamHandler.hashCode())
--> URLStreamHandler.hashCode()
--> URLStreamHandler.getHostAddress()
--> InetAddress.getByName()
0x04 代码实现与分析
测试代码关键部分
// 设置URL对象的hashCode为8888(序列化时不触发DNS)
Field filed = Class.forName("java.net.URL").getDeclaredField("hashCode");
filed.setAccessible(true); // 绕过权限检查
filed.set(url, 8888);
// 将URL对象放入HashMap(此时hashCode不为-1,不触发DNS)
hashMap.put(url, 23);
// 序列化前将hashCode设为-1(反序列化时将触发DNS)
filed.set(url, -1);
serializable(hashMap);
代码分析要点
- 使用反射获取并修改URL对象的
hashCode字段 - 通过
setAccessible(true)绕过Java语言权限控制 - 序列化前将
hashCode设为非-1值避免立即触发DNS - 反序列化前将
hashCode设为-1确保触发DNS请求
0x05 实际测试与验证
测试步骤
- 使用DNSLog平台(如dnslog.org)获取临时域名
- 在代码中设置目标URL为
http://[your-id].dnslog.biz - 执行序列化生成payload文件
- 在服务端模拟环境中反序列化该文件
- 观察DNSLog平台是否收到请求
服务端模拟代码
public static void unserializable() throws Exception {
FileInputStream filein = new FileInputStream("./hashmap.txt");
ObjectInputStream inputStream = new ObjectInputStream(filein);
Object o = inputStream.readObject(); // 触发反序列化
filein.close();
inputStream.close();
}
0x06 总结与扩展
URLDNS链价值
- 漏洞验证:确认目标是否存在反序列化漏洞
- 信息收集:可能获取系统版本等信息
学习建议
- 深入理解Java反射机制
- 掌握动态代理技术
- 研究其他常见反序列化漏洞链(如Commons Collections等)
防御措施
- 避免反序列化不可信数据
- 使用白名单机制限制可反序列化的类
- 考虑使用替代方案(如JSON、XML等更安全的序列化格式)