Java 代码审计---反序列化

Java 序列化是一种将对象转换为字节流的过程,以便可以将对象保存到磁盘上,将其传输到网络上,或者将其存储在内存中,以后再进行反序列化,将字节流重新转换为对象。
序列化在 Java 中是通过 java.io.Serializable 接口来实现的,该接口没有任何方法,只是一个标记接口,用于标识类可以被序列化。
当你序列化对象时,你把它包装成一个特殊文件,可以保存、传输或存储。反序列化则是打开这个文件,读取序列化的数据,然后将其还原为对象,以便在程序中使用。
序列化是一种用于保存、传输和还原对象的方法,它使得对象可以在不同的计算机之间移动和共享,这对于分布式系统、数据存储和跨平台通信非常有用。

序列化

序列化主要是将一个java对象转换为二进制字节流的过程,在学习反序列化之前,首先来学习一下序列化是什么,怎么进行,知其然,知其所以然。
序列化首先需要注意一下几点

  • 实现 Serializable 接口:序列化的对象必须要实现Serializable接口,这个接口是一个标记接口,没有任何方法,只是用于标识该类的对象可以被序列化。
  • 对象的成员变量可序列化: 如果一个类中的成员变量是基本数据类型或其他可序列化的对象,则该类的对象也是可序列化的。如果成员变量是不可序列化的对象,可以使用 transient 关键字进行标记,表示在序列化过程中不将该成员变量序列化,并且static变量正常情况下是不会被序列化的。
  • 版本控制: 在进行对象序列化时,需要注意版本控制,确保对象的类结构发生变化时不会导致序列化和反序列化的问题。可以通过 serialVersionUID 字段进行手动版本控制。
  • 对象的引用关系: 如果对象间存在引用关系,即一个对象引用了另一个对象,那么在序列化和反序列化时,需要确保所有相关的对象都可以正确地序列化和反序列化。
    ObjectOutputStream中的writeObject方法是java进行序列化的关键方法,下面是使用的具体方法
//创建一个FileOutputStream,其中写入ObjectOutputStream中的对象
FileOutputStream fileStream = new FileOutputStream(String file);

//创建ObjectOutputStream
ObjectOutputStream objStream = new ObjectOutputStream(fileStream);

//调用writeObject方法,该方法传入的是需要序列化的对象,并且该方法会将该对象进行序列化,写入到上面指定的输出流中:fileStream
objStream.writeObject(Object);

下面是序列化的示例
首先创建一个类,并且该类继承Serializable接口

package com.pwjcw.entity;  
  
import java.io.Serializable;  
  
public class Persion implements Serializable {  
    private String name;  
    private int age;  
  
    public Persion() {  
    }  
  
    @Override  
    public String toString() {  
        return "Persion{" +  
                "name='" + name + '\'' +  
                ", age=" + age +  
                '}';  
    }  
  
    public Persion(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
}

实现对该类的序列化

@Test  
public void TestSerialize() throws IOException {  
    Persion persion = new Persion("pwjcw", 1);  
    // 创建文件输出流,用于将对象序列化后的字节流写入文件  
    FileOutputStream f = new FileOutputStream("persion.ser");  
    // 创建对象输出流,用于将对象序列化后的数据写入文件  
    ObjectOutputStream outputStream = new ObjectOutputStream(f);  
    // 将 Person 对象进行序列化并写入文件  
    outputStream.writeObject(persion);  
    // 关闭对象输出流  
    outputStream.close();  
    // 关闭文件输出流  
    f.close();  
}

序列化后的数据

将一个对象进行序列化其实是将该对象的一些属性进行序列化,并不是对该对象的类,以及相关的方法也进行序列化为二进制数据。下面是persion.ser文件的二进制视图

在这里插入图片描述

serialVersionUID

在Java中,serialVersionUID是一个特殊的静态变量,用于标识序列化类的版本。当一个类被序列化时,它的serialVersionUID会被序列化到流中,以确保序列化和反序列化过程中类的版本一致性,如果反序列化时的serialVersionUID版本与本地对应的serialVersionUID版本不一致,则会导致反序列化失败。

当类的结构发生变化时(例如添加新的字段或方法),通过显式地指定serialVersionUID,可以确保旧版本的序列化数据可以与新版本的类兼容。如果不指定serialVersionUID,Java会根据类的结构自动生成一个,但是当类的结构发生变化时,自动生成的serialVersionUID也会改变,可能导致旧版本的序列化数据无法被正确反序列化

关于悖论的解释

上面也已经说到,serialVersionUID是一个静态变量,而静态变量正常情况下又不参与序列化,不过serialVersionUID是一个例外,这是java设计的一个特殊情况。

反序列化

反序列化和序列化相反,主要是从二进制字节流转换为java对象,可以通过ObjectInputStream类的readObject方法将传入的二进制流进行序列化到对象
下面是具体的使用示例

@Test  
public void TestUnSerialize() throws IOException, ClassNotFoundException {  
    //从文件中读取二进制字节流  
    FileInputStream fileInputStream=new FileInputStream("persion.ser");  
    //创建ObjectInputStream对象,并且传入FileInputStream读取到的二进制字节流  
    ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);  
    //调用readObject方法,并且转换为Persion对象  
    Persion persion= (Persion) objectInputStream.readObject();  
    //打印反序列化得到的persion对象  
    System.out.println(persion);  
}

反序列化导致rce的原因

在反序列化中,如果反序列化的目标类自定义了readObject方法,那么在反序列化时,将会调用目标类自定义的readObject方法,这是出现反序列化漏洞的根本原因。下面是一个演示示例。
目标类

package com.pwjcw.entity;  
  
import java.io.IOException;  
import java.io.ObjectInputStream;  
import java.io.Serializable;  
  
public class Persion implements Serializable {  
    private String name;  
    private int age;  
  
    public Persion() {  
    }  
  
    @Override  
    public String toString() {  
        return "Persion{" +  
                "name='" + name + '\'' +  
                ", age=" + age +  
                '}';  
    }  
  
    public Persion(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
    private void readObject(java.io.ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {  
        objectInputStream.defaultReadObject();  
        Runtime.getRuntime().exec("calc.exe");  
    }  
}

那么此时进行反序列化,就会调用Persion类的readObject方法,进而调用Runtime语句。
当前并不是所有的方法都会自定义readObject方法,不过后面的HashMap类自定义了,并且通过该类造成了URLDNS链的反序列化,后面文章会进行分析。

参考文档:

https://www.runoob.com/java/java-serialization.html
Java ObjectOutputStream 类 - Java教程 - 菜鸟教程 (cainiaojc.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/667616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++候捷stl-视频笔记2

深度搜索list list是双向链表:底部实现是环状双向链表 list内部除了存data之外,还要存一个前向指针prev和一个后向指针next list的iterator,当迭代器的时候,是从一个节点走到下一个节点,是通过访问next指针实现的 主要…

C语言:深入了解(联合体和枚举)

目录 联合体 联合体的类型的声明 联合体的特点 相同成员的结构体和联合体对比 联合体大小的计算 联合体的使用举例 联合体的类型:判断联合体是大端还是小端 枚举类型 枚举类型声明 枚举类型的优点 枚举类型的使用 联合体 联合体的类型的声明 像结构体⼀…

(含笔试题)深度解析数据在内存中的存储

目录 本章重点 前言: 1.整型在内存中的存储 1.1原码、反码、补码 原码 反码 补码 2.大小端字节序介绍 什么是大小端字节序: 为什么会有大小端字节序: 3.浮点数存储规则 本章重点 1. 整形在内存中的存储:原码、反码…

刷机 iPhone 进入恢复模式

文章目录 第 1 步:确保你有一台电脑(Mac 或 PC)第 2 步:将 iPhone 关机第 3 步:将 iPhone 置于恢复模式第 4 步:使用 Mac 或 PC 恢复 iPhone需要更多协助? 本文转载自:如果你忘记了 …

【嵌入式硬件】DRV8874电机驱动

目录 1 芯片介绍 1.1 特性简介 1.2 引脚配置 1.3 最佳运行条件 2 详细说明 2.1 PMODE配置控制模式 2.1.1 PH/EN 控制模式 2.1.2 PWM 控制模式 2.1.3 独立半桥控制模式 2.2 电流感测和调节 2.2.1 IPROPI电流感测 2.2.2 IMODE电流调节 3.应用 3.1设计要求 3.2 设计…

逆天工具一键修复图片,视频去码。本地部署超详细!!

上一篇文章:逆天工具一键修复图片,视频去码。简直不要太好用!-CSDN博客 根据上一篇文章展示的效果,本文章主要讲如何部署本地github开源项目。博主走了无数弯路,最后精化下来的步骤,超级详细!&a…

统计信号处理基础 习题解答10-5

题目 通过令 并进行计算来重新推导MMSE估计量。提示:利用结果 解答 首先需要明确的是: 上式是关于观测值x 的函数 其次需要说明一下这个结果 和教材一样,我们用求期望,需要注意的是,在贝叶斯情况下,是个…

Amis源码 embed渲染方法解析(json结构渲染原理):

js sdk中的渲染函数embed使用方式如下: const amis amisRequire("amis/embed"); const amisScoped amis.embed( self.$refs["mnode"],amisJSON, {}, amisEnv); //env会有默认值,默认值与传来的参数进行合并({默认值…

【学习Day5】操作系统

✍🏻记录学习过程中的输出,坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞👍🏻收藏⭐评论✍🏻指点🙏 学习编辑文章的时间不太够用,先放思维导图,后续复习完善细节。

【每日刷题】Day53

【每日刷题】Day53 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 1019. 链表中的下一个更大节点 - 力扣(LeetCode) 2. 116. 填充每个节点的下一…

mac多媒体影音库:Emby for Mac 中文版

Emby软件是一款功能强大的媒体服务器软件,旨在为用户提供丰富的多媒体体验。以下是关于Emby软件的详细介绍: 下载地址:https://www.macz.com/mac/7964.html?idOTI2NjQ5Jl8mMjcuMTg2LjE1LjE4Mg%3D%3D 主要功能 媒体管理:Emby允许用…

python编程:SQLite 管理图片数据库

在本博客中,我们将介绍如何使用 wxPython 和 sqlite3 模块构建一个 GUI 应用程序,该程序可以遍历指定文件夹中的所有图片,并将其信息存储到 SQLite 数据库中。 C:\pythoncode\new\InputImageOFFolderTOSqlite.py 项目简介 我们的目标是创建…

新版校园跑腿外卖独立版+APP+小程序前端外卖配送平台源码

同城校园跑腿外卖配送平台源码,这套目前全网还没有人分享过,这个是开源的,所以没有任何问题了,这套源码非常吊,支持自定义diy 你可以设计你的页面,设计你自己的风格,支持多校园,独立…

Java基础入门day62

day62 AJAX 概念 AJAX: Asynchronous Javascript And XML AJAX是一种无需重新加载整个网页的情况下,能够更新部分网页的技术 AJAX是一种用于创建快速动态网页的技术 通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新 传统…

Jvm(二)新生代和老年代与GC回收

目录 新生代和老年代 新生代 MinorGC 老年代(Old Generation) MajorGC Minor GC、Major GC 和 Full GC 三个GC具体区别和使用场景 JVM GC及内存调优的参数 调优建议 前言-与正文无关 ​ 生活远不止眼前的苦劳与奔波,它还充满了无…

【教程】自监督 对比学习,代码,爽学一波

from: https://docs.lightly.ai/self-supervised-learning/examples/simclr.html

1114 全素日

你好哇&#xff0c;新的一天开始啦&#xff01; solution 取数值的不同部分&#xff0c;联想到借助string #include<iostream> #include<string> using namespace std; bool judge(string s){int n atoi(s.c_str());if(n 1 || n 0) return false;for(int i 2…

基于51单片机的超声波测距—数码管显示

基于51单片机的超声波测距 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.HC-SR04模块测量距离&#xff0c;LED数码管显示距离&#xff1b; 2.测量范围&#xff1a;2cm-400cm&…

深度学习中的模型架构详解:RNN、LSTM、TextCNN和Transformer

深度学习中的模型架构详解&#xff1a;RNN、LSTM、TextCNN和Transformer 文章目录 深度学习中的模型架构详解&#xff1a;RNN、LSTM、TextCNN和Transformer循环神经网络 (RNN)RNN的优点RNN的缺点RNN的代码实现 长短期记忆网络 (LSTM)LSTM的优点LSTM的缺点LSTM的代码实现 TextCN…

[每周一更]-(第99期):MySQL的索引为什么用B+树?

文章目录 B树与B树的基本概念B树&#xff08;Balanced Tree&#xff09;B树&#xff08;B-Plus Tree&#xff09;对比 为什么MySQL选择B树1. **磁盘I/O效率**2. **更稳定的查询性能**3. **更高的空间利用率**4. **并发控制** 其他树结构的比较参考 索引是一种 数据结构&#x…