序列化与反序列化

Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程。

为什么需要序列化?

序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。

序列化为什么会产生安全问题?

只要服务端反序列化数据,客户端传递类的readObject中代码会自动执行,给予攻击者在服务器上运行代码的能力。

Java序列化基本流程

有如下三个文件,Person.java:

import java.io.Serializable;

public class Person implements Serializable {
// 需要实现Serializable接口才可以序列化
private String name;
private int age; public Person(){ } public Person(String name, int age) {
this.name = name;
this.age = age;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
",age=" + age +
'}';
}
}

序列化操作,SerializationTest.java:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream; public class SerializationTest {
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
} public static void main(String[] args) throws Exception{
Person person = new Person("a", 18);
serialize(person);
}
}

反序列化操作,UnserializeTest.java:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream; public class UnserializeTest {
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
} public static void main(String[] args) throws Exception {
Person person = (Person) unserialize("ser.bin");
System.out.println(person);
}
}

SerializationTest中首先生成一个person对象,然后将生成的person对象进行序列化操作,得到二进制文件ser.bin,接着在UnserializeTest中实现反序列化操作得到person对象,并打印出来:

Person{name='a',age=18}

注意:

  • (1)想要序列化的对象需要实现Serializable接口才可以序列化。
  • (2)使用transient标识的对象不参与序列化。

    在Person类中,name属性之前加上transient,改为private transient String name;之后再次尝试序列化和反序列化,输出结果:Person{name='null',age=18}
  • (3)静态成员变量不能被序列化,因为序列化是针对对象的,而静态成员变量属于类。

可能存在反序列化漏洞的形式

  • (1)入口类的readObject直接调用危险方法。

    Person类文件中重写了readObject方法,在readObject方法中执行命令:
package org.example;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable; public class Person implements Serializable {
private transient String name;
private int age; public Person(){ } public Person(String name, int age) {
this.name = name;
this.age = age;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
",age=" + age +
'}';
} private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
Runtime.getRuntime().exec("calc");
}
}

再次执行SerializationTest和UnserializeTest实现序列化和反序列化,在反序列化时会调用重写的readObject,从而执行其中的命令,弹出计算器:

  • (2)入口类参数中包含可控类,该类有危险方法,readObject时调用。

    要实现反序列化攻击,入口类最好是继承Serializable,重写readObject,调用常见函数,参数类型宽泛,jdk自带,比如HashMap:

  • (3)入口类中包含可控类,该类又调用其他有危险的方法的类,readObject时调用。

  • (4)构造函数/静态代码块等类加载时隐式执行。

Java原生序列化与反序列化的更多相关文章

  1. java原生序列化和Kryo序列化性能比较

    简介 最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括: 专门针对Java语言的:Kryo,FST等等 跨语言的:Protostuff,ProtoBuf,Thrift, ...

  2. java 对象序列化与反序列化

    Java序列化与反序列化是什么? 为什么需要序列化与反序列化? 如何实现Java序列化与反序列化? 本文围绕这些问题进行了探讨. 1.Java序列化与反序列化  Java序列化是指把Java对象转换为 ...

  3. Java对象序列化与反序列化一 JSON

    Java对象序列化与反序列化一 JSON 1. 依赖库 jackson-all-1.6.1.jar 2. 代码 public class Student {    private String nam ...

  4. Java对象序列化和反序列化的工具方法

    import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...

  5. Java之序列化和反序列化

    序列化的对象: package test_demo.SerializableOper; import java.io.Serializable; /* * 序列化对象需要实现序列号接口 * */ pu ...

  6. java之序列化与反序列化

    1.这里主要是介绍Protobuf提供的序列化与反序列化的高效性.相对于传统的java提供的序列化来说,Protobuf的效率提高了很多倍.但是也有不足的地方,就是proto在对象序列化的时候抛弃了很 ...

  7. Java基础—序列化与反序列化(转载)

    转载自: Java序列化与反序列化 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程. 2.为什么需要序列化 ...

  8. Java 中序列化与反序列化

    一. 序列化和反序列化概念 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.将程序中的对象,放入文 ...

  9. MessagePack Java Jackson 序列化和反序列化 POJO 为 MessagePack 的数组类型用来与 msgpack-java:0.6 保持兼容性

    在 msgpack-java 0.6 或者早期的版本中,POJO 在 MessagePack 中被序列化和反序列化为数组变量. 变量的顺序是基于 Java 类中变量的内部顺序了,这种本来是一种原生的序 ...

  10. JAVA的序列化与反序列化

    一.为什么要进行序列化 再介绍之前,我们有必要先了解下对象的生命周期,我们知道Java对象的生命周期,也即Java中的远程方法调用RMI也会被用到,在网络中要传输对象的话,则必须要对对象进行序列化,关 ...

随机推荐

  1. .NET 云原生架构师训练营(模块二 基础巩固 REST && RESTful)--学习笔记

    2.3.1 Web API -- REST && RESTful 什么是 REST,什么是 RESTful RESTful API 设计 RESTful 成熟度模型 什么是 REST, ...

  2. google recaptcha 谷歌人机身份验证超详细使用教程,前端/后端集成说明

    壹 ❀ 引 在日常页面交互中,验证码使用是极为频繁的,登录注册验证,非机器人操作验证等等,它遍布于每一个网站.说到验证码实现,Goole Recaptcha是一个非常不错的选择,那么希望通过本文的使用 ...

  3. NC204871 求和

    题目链接 题目 题目描述 已知有 \(n\) 个节点,有 \(n-1\) 条边,形成一个树的结构. 给定一个根节点 \(k\) ,每个节点都有一个权值,节点i的权值为 \(v_i\) . 给 \(m\ ...

  4. Oracle ascii函数

    一  简介 Oracle ascii函数用于返回单个字符的数字代号. 二  语法 ASCII( single_character ) 参数说明: 代表只能输入单个字符,如果输入多个,oracle只会返 ...

  5. Innodb存储引擎的文件

    目录 概述 参数文件 日志文件 错误日志 慢查询日志 查询日志 二进制日志 binary log 二进制日志的配置 二进制日志的作用 二进制日志的保存 socket 套接字文件 pid文件 MySQL ...

  6. python利用random模块随机生成MAC地址和IP地址

      import random   def randomMac(): macstring = "0123456789abcdef"*12 macstringlist=random. ...

  7. 【Android逆向】frida 破解 jwxdxnx02.apk

    apk 路径: https://pan.baidu.com/s/1cUInoi 密码:07p9 这题比较简单,主要是用于练习frida 1. 安装apk到手机 需要输入账号密码 2. 使用jdax 查 ...

  8. 好用的OCR文本识别工具

    之所以会用到OCR工具,是因为在看一些扫描版的PDF文档时,有时候需要复制粘贴一些文字,特别是技术性文档,对于一些命令或者代码片段需要复制出来执行验证. 网络上有许多推荐OCR工具的文章,但是大多数都 ...

  9. 临时修改session日期格式冲突问题

    输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01' alter session set NLS_DATE_LANGUAGE ...

  10. 红胖子(红模仿)的博文大全:开发技术集合大版本更新v4.0.0

    <红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术.树莓派.三维.OpenCV.OpenGL.ffmpeg.OSG.单片机.软硬结合等等)持续更新中...>大版本更新,更新后版本 ...