Loading ...
Java 反序列化漏洞:从原理到防护全解析

什么是 Java 序列化与反序列化

Java 序列化是将内存中的对象转换为字节流的过程,目的是实现对象在不同存储介质(如内存、文件、数据库)或网络间的高效传递 —— 例如网络通信时,发送方需通过序列化将对象转为字节流才能传输;而反序列化则是其逆操作,接收方通过该过程将字节流还原为可直接使用的原始对象。

 

从技术实现来看,序列化依赖ObjectOutputStream类的writeObject()方法,反序列化则通过ObjectInputStream类的readObject()方法完成。值得注意的是,被操作的类必须实现SerializableExternalizable接口:

 

  • Serializable是一个标记接口,不含任何方法,仅作为 “允许序列化” 的权限标识;
  • Externalizable作为Serializable的子类,要求必须重写writeExternal()(序列化时执行)和readExternal()(反序列化时执行)方法,可自定义序列化逻辑。

 

这一机制的应用场景十分广泛,包括 RPC 框架中的跨服务对象传输、对象通过文件或数据库进行持久化存储、分布式系统中不同节点间的对象共享等。

Java 序列化数据结构特点

Java 序列化数据以二进制形式传输,分析或调试时通常以十六进制格式显示。其前四个字节固定,用于标识序列化数据的开始和版本:AC ED 是魔数,标识为 Java 序列化数据;00 05 是版本号,对应 Java 1.5 及以上版本的序列化协议。

Java 序列化与反序列化代码示例

基础类定义

package com.lang.serializable.pojo;
import java.io.Serializable;
public class People implements Serializable {
    // 序列化版本号,确保反序列化时类结构兼容
    private static final Long serialVersionUID = 60L;
    private String name;
    public People(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "People{" + "name='" + name + '\'' + '}';
    }
}

序列化操作

@Test
public void test01() throws IOException {
    People jack = new People("Jack");
    // 创建输出流,将对象序列化到文件
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./obj.txt"));
    oos.writeObject(jack); // 序列化对象
    oos.close();
}
// 结果:对象被转化为二进制数据,写入obj.txt文件

反序列化操作

@Test
public void test02() throws IOException, ClassNotFoundException {
    // 创建输入流,从文件读取字节流并反序列化
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./obj.txt"));
    People people = (People) ois.readObject(); // 反序列化对象
    System.out.println(people); // 输出:People{name='Jack'}
    ois.close();
}

Java 反序列化漏洞原理及触发条件

漏洞本质

当反序列化过程处理攻击者构造的恶意字节流时,可能触发危险操作,如命令执行、代码注入等。

触发关键点

  • 危险方法重写:类重写 readObject () 或 readExternal () 时,若包含未校验的危险操作(如 Runtime.getRuntime ().exec ()),可能被利用。
  • 输入校验缺失:开发者未对反序列化的字节流来源和内容进行严格校验,导致恶意对象被解析。

自定义序列化策略与漏洞演示

重写序列化方法的类

package com.lang.serializable.pojo;
import java.io.*;
public class People implements Serializable {
    private static final Long serialVersionUID = 60L;
    private String name;
    private String pwd;
    // 构造方法、getter/setter略
    @Override
    public String toString() {
        return "People{" + "name='" + name + "', pwd='" + pwd + '\'' + '}';
    }
    private void writeObject(ObjectOutputStream out) throws IOException {
        ObjectOutputStream.PutField putField = out.putFields();
        putField.put("name", name); // 仅序列化name字段
        out.writeFields();
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField getField = in.readFields();
        name = (String) getField.get("name", "rose");
        // 危险示例:若此处添加命令执行
        // Runtime.getRuntime().exec("mkdir lang");
    }
}

漏洞演示过程

  1. 序列化对象:
@Test
public void test03() throws IOException {
    People jack = new People("Jack", "123123");
    System.out.println(jack); // 输出:People{name='Jack', pwd='123123'}
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./obj.txt"));
    oos.writeObject(jack);
    oos.close();
}
说明:pwd 字段因自定义序列化未被写入 obj.txt。
  1. 反序列化对象:
@Test
public void test04() throws Exception {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./obj.txt"));
    People people = (People) ois.readObject();
    System.out.println(people); // 输出:People{name='Jack', pwd='null'}
}
  1. 恶意利用(命令执行):若在 readObject () 中添加 Runtime.getRuntime ().exec (“mkdir lang”),反序列化时将执行系统命令,创建 lang 文件夹。

Java 反序列化漏洞安全建议

  1. 避免危险操作:不在 readObject ()、readExternal () 等方法中执行系统命令、文件操作等敏感行为。
  2. 严格输入校验:对反序列化的字节流来源进行验证,确保来自可信渠道。
  3. 白名单限制:限制可反序列化的类范围,仅允许安全的已知类。
  4. 及时更新修复:升级 JDK 及依赖框架(如 Log4j2、Fastjson),修复已知反序列化漏洞。
本文内容仅供学习交流使用,旨在普及网络安全知识、提升安全防护意识。文中涉及的技术解析与案例分析,均以合法合规的网络安全研究为前提,严禁用于任何未经授权的攻击、破坏或侵犯他人权益的行为。
网络空间不是法外之地,使用者需严格遵守《中华人民共和国网络安全法》《数据安全法》等相关法律法规,对自身行为承担全部法律责任。维护网络安全是每个公民的责任,让我们共同抵制网络违法活动,共建安全、健康的网络环境。
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇