Java 反序列化漏洞 学习笔记

前言

Java的反序列化漏洞我感觉应该是比较常见而且危害较大的漏洞,而Java 反序列化技术大量应用于 JRMI( Java远程方法调用 ) , JMX( Java管理扩展 ) , JMS( Java消息服务 ) 中,因此 Java RMI 服务也算是 Java 反序列化漏洞的高发地 ,而前面也学过了Java RMI相关的知识,今天就来学一下Java 反序列化漏洞相关原理

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

Java 序列化就是把一个 Java Object 变成一个二进制字节数组 , 即 byte[] .

Java 反序列化就是把一个二进制字节数组(byte[]) 变回 Java 对象 , 即 Java Object .

Java 序列化/反序列化的目的无非就是用于 " 数据存储 " 或 " 数据传输 " .

实现反序列化需要满足的条件

Serializable

如果一个类要实现序列化操作 , 则必须实现 Serializable 接口

Serializable是一个空接口,接口中没有方法和属性字段 , 仅用于标识序列化的语义 , 代表该类可以进行序列化/反序列化操作 .

在序列化或反序列化过程中需要进行特殊处理的类要实现下面三个方法:
在这里插入图片描述
这里在额外说一下serialVersionUID 属性,每个可序列化的类在序列化时都会关联一个版本号 , 这个版本号就是 serialVersionUID 属性

在反序列化过程中会根据这个版本号来判断序列化对象的发送者和接收着是否有与该序列化/反序列化过程兼容的类 .( 简单的说就是序列化过程和反序列化过程都需要被序列化的类 , 通过 serialVersionUID 属性来判断这两个类的版本是否相同 , 是否是同一个类 ) . 如果不相同 , 则会抛出 InvalidClassException 异常

serialVersionUID 属性必须通过 static final long 修饰符来修饰 .

如果可序列化的类未声明 serialVersionUID 属性 , 则 Java 序列化时会根据类的各种信息来计算默认的 serialVersionUID 值 . 但是 Oracle 官方文档强烈建议所有可序列化的类都显示声明 serialVersionUID 值 .

Externalizable

不仅可以通过继承 Serializable 接口来标识某个类是可序列化的,事实上 , 还可以通过Externalizable 接口,该继承了 Serializable 接口

public interface Externalizable extends java.io.Serializable

通过 Externalizable 接口实现序列化和反序列化操作会相对麻烦一点 , 因为我们需要手动编写 writeExternal()方法和readExternal()方法 , 这两个方法将取代定制好的 writeObject()方法和 readObject()方法 .

那什么时候会使用 Externalizable 接口呢 ?

当我们仅需要序列化类中的某个属性 , 此时就可以通过 Externalizable 接口中的 writeExternal() 方法来指定想要序列化的属性 . 同理 , 如果想让某个属性被反序列化 , 通过 readExternal() 方法来指定该属性就可以了.

此外 , Externalizable 序列化/反序列化还有一些其他特性 , 比如 readExternal() 方法在反序列化时会调用默认构造函数 , 实现 Externalizable 接口的类必须要提供一个 Public 修饰的无参构造函数等等

Externalizable 与 Serializable 一文中 , 简单的总结了 Serializable 和 Externalizable 两个接口的区别及优劣 .

在这里插入图片描述
因此一般还是使用Serializable

关于writeObject() 与 readObject()

上面也说过了,在最简单的情况下 , 开发人员会使用 Serializable 类来实现序列化与反序列化 . 即使是使用Externalizable类该类也是继承自Serializable,而Serializable类的序列化与反序列化离不开 writeObject() 和 readObject() 两个方法.

在这里插入图片描述
从官方文档可以看出 , 在序列化和反序列化时需要实现上述两个方法 , 这两个方法的参数是ObjectOutputStream和ObjectInputStream类型的 . 下面来简单介绍下这个两个类 .

java.io.ObjectOutputStream和writeObject()

ObjectOutputStream 类会将支持 java.io.Serializable 接口的 Java对象( 包括部分图形对象 ) 的原始数据类型写入 OutputStr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值