JAVA反序列化初食
字数 1270 2025-08-24 07:48:22

Java反序列化漏洞分析与利用

基本概念

序列化与反序列化

  • 序列化:将类实例转换为字节流的过程
  • 反序列化:将字节流转换回类实例的过程
  • 关键方法
    • 序列化时自动调用writeObject
    • 反序列化时自动调用readObject

可序列化类的条件

  1. 实现java.io.Serializable接口
  2. 该类所有属性必须可序列化
  3. 如果有属性不可序列化,必须使用transient关键字标记

反序列化漏洞利用条件

  1. 存在反序列化接口,能够提交序列化数据
  2. 存在可利用的类,最终可以实现文件读取、写入或执行操作

漏洞利用关键点

  1. 需要有一个可以提交序列化字节流的地方
  2. 有可以被利用的类
  3. 类序列化后,重点在于执行了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查询请求
  • 主要用于验证漏洞存在和判断服务器是否出网

利用原理

  1. HashMap存在readObject方法,里面调用了hash方法处理key
  2. hash方法调用了key的hashCode方法
  3. 当key是URL对象时,会调用URL对象的hashCode
  4. URL类的hashCode方法会调用handler属性的hashCode
  5. URLStreamHandlerhashCode方法调用getHostAddress
  6. 最终调用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);
        }
    }
    // ...
}

防御措施

  1. 避免反序列化不受信任的数据
  2. 使用白名单验证反序列化的类
  3. 使用ObjectInputFilter限制反序列化的类
  4. 及时更新存在漏洞的第三方库
  5. 对关键类重写readObject方法,添加验证逻辑

总结

Java反序列化漏洞利用的关键在于:

  1. 找到反序列化入口点
  2. 构造合适的利用链(如URLDNS、CC链等)
  3. 利用readObject方法的自动执行特性
  4. 结合JNDI等特性扩大攻击面

理解这些原理和利用技术对于安全研究和防御至关重要。

Java反序列化漏洞分析与利用 基本概念 序列化与反序列化 序列化 :将类实例转换为字节流的过程 反序列化 :将字节流转换回类实例的过程 关键方法 : 序列化时自动调用 writeObject 反序列化时自动调用 readObject 可序列化类的条件 实现 java.io.Serializable 接口 该类所有属性必须可序列化 如果有属性不可序列化,必须使用 transient 关键字标记 反序列化漏洞利用条件 存在反序列化接口,能够提交序列化数据 存在可利用的类,最终可以实现文件读取、写入或执行操作 漏洞利用关键点 需要有一个可以提交序列化字节流的地方 有可以被利用的类 类序列化后,重点在于执行了 readObject 方法 实战示例 示例代码分析 漏洞点 : readObject 方法中直接执行了 username 的内容,如果攻击者能够控制序列化数据,就可以执行任意命令。 常见利用链 URLDNS链 特点 : 不需要其他依赖,使用原生Java库 支持反序列化后触发DNS查询请求 主要用于验证漏洞存在和判断服务器是否出网 利用原理 : HashMap 存在 readObject 方法,里面调用了 hash 方法处理key hash 方法调用了key的 hashCode 方法 当key是 URL 对象时,会调用 URL 对象的 hashCode URL 类的 hashCode 方法会调用 handler 属性的 hashCode URLStreamHandler 的 hashCode 方法调用 getHostAddress 最终调用 InetAddress.getByName(host) ,触发DNS查询 利用工具 :ysoserial 使用示例 : CC链 (Commons Collections链) 特点 : 利用Apache Commons Collections库中的漏洞 可以执行任意代码 需要目标系统使用特定版本的Commons Collections库 JNDI注入 基本概念 JNDI (Java Naming and Directory Interface) : Java命名和目录接口 使配置参数和代码解耦的规范或思想 允许在不修改代码的情况下更改配置 核心组件 : Name :将Java对象通过命名绑定到容器环境 Directory :将对象的所有属性信息保存在容器环境中 配置示例 context.xml : 数据库工具类示例 : 防御措施 避免反序列化不受信任的数据 使用白名单验证反序列化的类 使用 ObjectInputFilter 限制反序列化的类 及时更新存在漏洞的第三方库 对关键类重写 readObject 方法,添加验证逻辑 总结 Java反序列化漏洞利用的关键在于: 找到反序列化入口点 构造合适的利用链(如URLDNS、CC链等) 利用 readObject 方法的自动执行特性 结合JNDI等特性扩大攻击面 理解这些原理和利用技术对于安全研究和防御至关重要。