JAVA反序列化初食
字数 1270 2025-08-24 07:48:22
Java反序列化漏洞分析与利用
基本概念
序列化与反序列化
- 序列化:将类实例转换为字节流的过程
- 反序列化:将字节流转换回类实例的过程
- 关键方法:
- 序列化时自动调用
writeObject - 反序列化时自动调用
readObject
- 序列化时自动调用
可序列化类的条件
- 实现
java.io.Serializable接口 - 该类所有属性必须可序列化
- 如果有属性不可序列化,必须使用
transient关键字标记
反序列化漏洞利用条件
- 存在反序列化接口,能够提交序列化数据
- 存在可利用的类,最终可以实现文件读取、写入或执行操作
漏洞利用关键点
- 需要有一个可以提交序列化字节流的地方
- 有可以被利用的类
- 类序列化后,重点在于执行了
readObject方法
实战示例
示例代码分析
package com.ctfshow.entity;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = -3254536114659397781L;
private String username;
public User(String username) {
this.username = username;
}
public String getName() {
return this.username;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
Runtime.getRuntime().exec(this.username);
}
}
漏洞点:readObject方法中直接执行了username的内容,如果攻击者能够控制序列化数据,就可以执行任意命令。
常见利用链
URLDNS链
特点:
- 不需要其他依赖,使用原生Java库
- 支持反序列化后触发DNS查询请求
- 主要用于验证漏洞存在和判断服务器是否出网
利用原理:
HashMap存在readObject方法,里面调用了hash方法处理keyhash方法调用了key的hashCode方法- 当key是
URL对象时,会调用URL对象的hashCode URL类的hashCode方法会调用handler属性的hashCodeURLStreamHandler的hashCode方法调用getHostAddress- 最终调用
InetAddress.getByName(host),触发DNS查询
利用工具:ysoserial
使用示例:
java -jar ysoserial.jar URLDNS 'http://127.0.0.1' > 1.ser
CC链 (Commons Collections链)
特点:
- 利用Apache Commons Collections库中的漏洞
- 可以执行任意代码
- 需要目标系统使用特定版本的Commons Collections库
JNDI注入
基本概念
JNDI (Java Naming and Directory Interface):
- Java命名和目录接口
- 使配置参数和代码解耦的规范或思想
- 允许在不修改代码的情况下更改配置
核心组件:
- Name:将Java对象通过命名绑定到容器环境
- Directory:将对象的所有属性信息保存在容器环境中
配置示例
context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jndi/user"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="root"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/blog"
maxTotal="8"
maxIdle="4"/>
</Context>
数据库工具类示例:
public class DbUtil {
// ...
private DbUtil() {
try {
Context context = new InitialContext();
dataSource = (DataSource) context.lookup("java:comp/env/jndi/user");
context.close();
this.connection = dataSource.getConnection();
} catch (NamingException | SQLException e) {
throw new RuntimeException(e);
}
}
// ...
}
防御措施
- 避免反序列化不受信任的数据
- 使用白名单验证反序列化的类
- 使用
ObjectInputFilter限制反序列化的类 - 及时更新存在漏洞的第三方库
- 对关键类重写
readObject方法,添加验证逻辑
总结
Java反序列化漏洞利用的关键在于:
- 找到反序列化入口点
- 构造合适的利用链(如URLDNS、CC链等)
- 利用
readObject方法的自动执行特性 - 结合JNDI等特性扩大攻击面
理解这些原理和利用技术对于安全研究和防御至关重要。