Java序列化、反序列化、反序列化漏洞
1 序列化和反序列化
1.1 概念
Java 中序列化的意思是将运行时的对象转成可网络传输或者存储的字节流的过程。而反序列化正相反,是把字节流恢复成对象的过程。
1.2 序列化可以做什么?
- 持久化存储:将对象状态保存到存储设备(如硬盘)中,以便于后续读取使用。
- 网络传输:将对象转换成字节流,通过网络发送给另一个 JVM 实例,接收方再将字节流转回对象。
- 深度复制:通过序列化与反序列化可以实现对象的深复制,即创建一个新的对象,并且新对象的数据与原对象相同,但是它们在内存中的地址不同。
3 实现方式
3.1 Java 原生方式
step1:实现 Serializable 接口
要使一个类的对象能够被序列化,只需要让这个类实现 Serializable 接口即可。Serializable 是一个标记接口,它没有定义任何方法。例如:
public class Person implements Serializable {
// 可选,用于版本控制
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
step2:使用 ObjectOutputStream#writeObject() 方法序列化。例如:
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\test.bin"));
oos.writeObject(new Person("zhangsan",18));
}
step3:使用 ObjectInputStream#readObject() 方法反序列化。例如:
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Paths.get("D:\test.bin")));
Person p = (Person) ois.readObject();
System.out.println(p);
}
// 打印 Person{name='zhangsan', age=18}
3.2 第三方方式
使用 Java 原生序列化方式序列化的对象只能被 Java 读取(反序列化),所以可以考虑先把对象转成一种通用的格式——如 JSON 字符串,然后把 JSON 字符串转成字节流进行网络传输,从而实现跨平台或者跨语言。
这个时候就可以使用市面上开源的序列化工具了,比如 JSON、Xml、hessian等。
4 反序列化漏洞
反序列化是把数据流转成对象,那么万一数据流被人恶意加工过呢?
拿 Java 原生的反序列化举例,反序列化需要调用 ObjectInputStream#readObject() 方法,但是如果数据流的对象自己重写了 readObject(),那 Java 便会调用自己的这个 readObject() 方法,这就给了攻击者可乘之机,他们就能在自己的 readObject() 方法里写攻击代码。
我们改造一下上面例子里的 Person 类:
@Data
public class Person implements Serializable {
// 可选,用于版本控制
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
// 重写了 readObject 方法,反序列化时便会调用此处
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject(); //这一步是先让反序列化读取的时候按照默认的方法执行
Runtime.getRuntime().exec("calc"); //这一步是攻击代码,作用是打开windows系统计算器
}
}
此时再去执行反序列化便会打开系统的计算器,如果把打开计算器改成别的攻击代码,攻击者便能实现对系统的攻击。
为什么 Java 会允许我们重写 readObject,并让服务端调用我们的 readObject 呢?其实这么做的原因是为了方便定制化某些类的序列化方法,比如 HashMap 类就重写了 readObject 方法,原因是由于 HashMap 内部使用了一些特定的数据结构(如数组和链表/红黑树),直接反序列化可能无法正确地恢复这些内部结构。因此,readObject 方法会负责根据序列化的数据正确地重建这些内部结构。
Java序列化、反序列化、反序列化漏洞的更多相关文章
- java 序列化和反序列化的底层实现原理
出处:序列化和反序列化的底层实现原理是什么? 一.基本概念1.什么是序列化和反序列化 (1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过 ...
- Java序列化与反序列化
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- [转] Java序列化与反序列化
原文地址:http://blog.csdn.net/wangloveall/article/details/7992448 Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java ...
- Java序列化与反序列化(Serializable)
Java序列化与反序列化(Serializable) 特别注意: 1.要序列化的类必须实现Serializable借口 2.在反序列化(读取对象)的时候必须额外捕获EOFException 3.序列化 ...
- Java基础(五)-Java序列化与反序列化
.output_wrapper pre code { font-family: Consolas, Inconsolata, Courier, monospace; display: block !i ...
- JAVA序列化和反序列化XML
package com.lss.utils; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.Bu ...
- Java序列化与反序列化(实践)
Java序列化与反序列化(实践) 基本概念:序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据. 昨天在一本书上 ...
- java序列化与反序列化(转)
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...
- Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?
Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节 ...
- (记录)Jedis存放对象和读取对象--Java序列化与反序列化
一.理论分析 在学习Redis中的Jedis这一部分的时候,要使用到Protostuff(Protobuf的Java客户端)这一序列化工具.一开始看到序列化这些字眼的时候,感觉到一头雾水.于是,参考了 ...
随机推荐
- 顺序表_C
// Code file created by C Code Develop #include "ccd.h" #include "stdio.h" #incl ...
- OpenAI深夜丢炸弹硬杠谷歌搜索
这几年科技变革太快,AI更是飞速发展,作为一名IT老兵,使用过的搜索引擎也是一换再换.这不,刚消停了一段时间的OpenAI又丢出一个炸弹SearchGPT,直接跟谷歌掀桌子了. 1.谷歌搜索的无奈 早 ...
- Netty的源码分析和业务场景
Netty 是一个高性能.异步事件驱动的网络应用框架,它基于 Java NIO 构建,广泛应用于互联网.大数据.游戏开发.通信行业等多个领域.以下是对 Netty 的源码分析.业务场景的详细介绍: 源 ...
- 【ElasticSearch】02 查询操作
准备样本: Elasticsearch 提供了基于 JSON 提供完整的查询 DSL 来定义查询 查询条件还适用于删除操作 创建索引: # PUT http://127.0.0.1:9200/st ...
- Meta公司的Llama3大语言模型
Github地址: https://github.com/meta-llama/llama3 官方介绍: https://ai.meta.com/blog/meta-llama-3/ 官方项目主页: ...
- NVIDIA一直宣传的DPU是个啥东西,啥用处? —— NVIDIA BlueField-3 DPU
地址: https://www.bilibili.com/video/BV1ys4y1z7nS/ 无意间看到了些比较靠谱的解释: (来自地址:https://www.bilibili.com/vide ...
- 如果一个windows主机上插两个蓝牙适配器会如何???——由于 Windows 无法加载这个设备所需的驱动程序,导致这个设备工作异常。 (代码 31)——windows主机蓝牙适配器驱动错误排查
事情是这样的,在某鱼上挂了一个蓝牙适配器,是自己多年前买的,给自己的老电脑用的,那一台老电脑主板上没有自带蓝牙,于是就在某东上买了一个蓝牙适配器: 但是这几年新买的电脑都自带蓝牙,于是准备把这个适配器 ...
- 使用 Apache DolphinScheduler 进行 EMR 任务调度
By AWS Team 前言 随着企业规模的扩大,业务数据的激增,我们会使用 Hadoop/Spark 框架来处理大量数据的 ETL/聚合分析作业,⽽这些作业将需要由统一的作业调度平台去定时调度. 在 ...
- flex布局被内容被撑开及flex布局下定宽元素被压缩
实现效果使用flex进行左右布局,左边定宽200px,右边自适应,当右边内容过多,造成右边盒子被撑开,会造成两种问题 左边定宽盒子被压缩解决办法: flex-grow:0;//是否自动增长空间 fle ...
- AtCoder Beginner Contest 327 D
AtCoder Beginner Contest 327D D - Good Tuple Problem (atcoder.jp)(种类并查集,二分图染色) 算法学习笔记(7):种类并查集 附上典题: ...