[Web 漏洞] Java 反序列化漏洞

文章介绍了Java中的序列化与反序列化概念,包括它们的作用,如对象持久化和跨平台传输。Java序列化通过实现Serializable接口来实现,使用ObjectOutputStream和ObjectInputStream进行操作。同时,文章提到了序列化过程中的安全问题,如通过重写readObject()方法可能引入的恶意代码执行风险。
摘要由CSDN通过智能技术生成

⚽一.Java 序列化与反序列化

🍉 1.序列化是干啥用的? 🌈 🌈 🌈

序列化的原本意图是希望对一个Java对象作一下“变换”,变成字节序列,这样一来方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,另外变换成字节序列也更便于网络运输和传播,所以概念上很好理解:

  • 序列化:把Java对象转换为字节序列。
  • 反序列化:把字节序列恢复为原先的Java对象。

而且序列化机制从某种意义上来说也弥补了平台化的一些差异,毕竟转换后的字节流可以在其他平台上进行反序列化来恢复对象。

🌈2.常见序列化与反序列化形式:

  • XML
  • JSON
  • Protobuf

⚽ 二.序列化和反序列化地实现

🌾1.JDK类库提供的序列化API: 🥝 🥝 🥝

  • java.io.ObjectOutputStream
    表示对象输出流,其中writeObject(Object obj)方法可以将给定参数的obj对象进行序列化,将转换的一连串的字节序列写到指定的目标输出流中。
  • java.io.ObjectInputStream
    该类表示对象输入流,该类下的readObject(Object obj)方法会从源输入流中读取字节序列,并将它反序列化为一个java对象并返回。

序列化要求:

实现序列化的类对象必须实现了Serializable类或Externalizable类才能被序列化,否则会抛出异常。

💐2.Serializable 如何序列化对象?

举个例子,假如我们要对Student类对象序列化到一个名为student.txt的文本文件中,然后再通过文本文件反序列化成Student类对象:

  • Student类定义
import java.io.Serializable;
public class Student implements Serializable {

    private String name;
    private Integer age;
    private Integer score;
 
    @Override
    public String toString() {
        return "Student:" + '\n' +
        "name = " + this.name + '\n' +
        "age = " + this.age + '\n' +
        "score = " + this.score + '\n'
        ;
    }
 
    // ... 其他省略 ...
}
1.这段代码定义了一个 Java 类 Student,它实现了 Serializable 接口。
Serializable 接口是 Java API 中的一种标记接口,用于指示实现该接口的类可以被序列化(即可以将对象转换为字节流进行传输或持久化)。
2.Student 类有三个私有属性:name、age 和 score,分别表示学生的姓名、年龄和成绩。
3.此外,Student 类还重写了 toString() 方法,以便在打印对象时输出更易读的信息。
toString() 方法返回一个字符串,其中包括 "Student:" 这个固定前缀,以及三个字段的值,
每个字段都单独占一行,并且用 \n 分隔。
  • 序列化
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public static void serialize(  ) throws IOException {

    Student student = new Student();
    student.setName("CodeSheep");
    student.setAge( 18 );
    student.setScore( 1000 );

    ObjectOutputStream objectOutputStream = 
        new ObjectOutputStream( new FileOutputStream( new File("student.txt") ) );
    objectOutputStream.writeObject( student );
    objectOutputStream.close();
 
    System.out.println("序列化成功!已经生成student.txt文件");
    System.out.println("==============================================");
}
    1创建一个Student 类的对象stu。
    2.利用ObjectOutputStream.writeObject() 方法进行序列化,并输出到文件student.txt中。
  • 反序列化
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public static void deserialize(  ) throws IOException, ClassNotFoundException {
    ObjectInputStream objectInputStream = 
        new ObjectInputStream( new FileInputStream( new File("student.txt") ) );
    Student student = (Student) objectInputStream.readObject();
    objectInputStream.close();
 
    System.out.println("反序列化结果为:");
    System.out.println( student );
}
   1. 从文件student.txt中读取字节流,并利用ObjectInputStream.readObject() 方法进行反序列化,传给对象student。
   2.输出对象student。
  • 运行结果
序列化成功!已经生成student.txt文件
==============================================
反序列化结果为:
Student:
name = CodeSheep
age = 18
score = 1000

其实Serializable接口也仅仅只是做一个标记用!!!它告诉代码只要是实现了Serializable接口的类都是可以被序列化的!然而真正的序列化动作不需要靠它完成。

注意事项:

  • 一个实现Serializable 接口的子类也是可以被序列化的。
  • 静态成员变量是不能被序列化。
  • transient 标识的对象成员变量不参与序列化。
  • Serializable 在序列化和反序列化过程中大量使用了反射,因此其过程会产生的大量的内存碎片。
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java 语言的反射机制。
简单来说,反射机制指的是程序在运行时能够获取自身的信息。
在Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。
  • writeObject() 方法和readObject() 方法可以重写。

🌞3.触发危险函数 🌈 🌈 🌈

Student 类中通过重写readObject() 方法。反序列化时,自动调用自己的readObject() 方法,该方法中包含恶意代码,导致命令执行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaynell

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值