初识Java反序列化漏洞

news2024/9/30 13:48:14

目录

为什么需要序列化?

序列化与反序列化基础案例

Serializable 接口

序列化对象

反序列化对象

Java 反序列化漏洞

readObject()


  • 序列化:将对象的状态信息转换为可以存储或传输的形式的过程,即将对象转换为字节序列。
  • 反序列化:是序列化的逆过程,即将字节序列恢复为对象。

为什么需要序列化?

  • 对象持久化:将对象的状态保存到文件中,以便在程序终止运行后能够重新加载这些对象。
  • 深拷贝:通过序列化一个对象到一个字节流,然后反序列化它到一个新的对象实例,可以实现对象的深拷贝。
  • 网络传输:在网络中传输对象时,需要将对象序列化为字节序列,然后在接收端反序列化以恢复对象。

序列化与反序列化基础案例

Serializable 接口

Serializable 接口是java.io包中的一个标记接口(marker interface),它没有定义任何方法。当一个类实现了Serializable接口时,它表明这个类的对象可以被序列化。即如果一个类的对象需要序列化,则这个类必须实现Serializable

  • import java.io.Serializable 用于将java.io包中的Serializable接口引入到当前类中。
  • serialVersionUID 用于在序列化和反序列化过程中确保版本兼容性。

定义一个可序列化的类

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1L; // 用于版本控制  
    private String name;
    private int age;

    // 构造函数  
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getter 和 Setter  
    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;
    }

    // toString 方法方便打印对象信息  
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

序列化对象

将 User 类的对象序列化为一个文件

import java.io.FileOutputStream;  //用于向文件写入数据
import java.io.IOException;    //抛出异常
import java.io.ObjectOutputStream; //将对象序列化为字节序列并写入到输出流中

public class SerializeDemo {
    public static void serialize(User user, String filePath) {  
        try (FileOutputStream fileOut = new FileOutputStream(filePath);  //创建一个FileOutputStream对象fileOut,用于向指定的文件路径写入数据。
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) { //基于fileOut创建了一个ObjectOutputStream对象out,这个对象用于 将对象序列化为字节序列并写入到fileOut中。
            out.writeObject(user); // 将User对象序列化到文件  
            System.out.printf("Serialized data is saved in %s%n", filePath);
        } catch (IOException i) {
            i.printStackTrace();
        }
    }

    public static void main(String[] args) {
        User user = new User("John Doe", 30);
        serialize(user, "user.ser"); // 序列化User对象到user.ser文件  
    }
}

文件后缀 .ser 一种约定俗成的命名方式,有助于开发者识别文件的用途和内容。实际上,你可以使用任何扩展名来保存序列化后的数据,只要确保在反序列化时能够正确地指定文件路径即可。但是,为了保持代码的清晰性和易读性,建议使用像 .ser、.dat、.obj 等能够表明文件内容的扩展名。

Java 序列化将对象的状态信息转换为二进制格式的字节序列,这些字节序列被存储在文件中(如 user.ser)。这些二进制数据具有以下特点:

  1. 非文本格式:内容是以二进制形式存储的,不是人类可读的文本。
  2. 包含对象状态:包含了序列化对象的所有非瞬态、非静态字段的当前值。
  3. 元数据:可能还包含了关于对象类的元数据信息,以便在反序列化时能够重新构造对象。
  4. 版本控制(可选):如果类定义了 serialVersionUID,则这个版本号也会被序列化,用于版本兼容性检查。
  5. 平台依赖:虽然 Java 序列化是 Java 平台的一部分,但序列化数据的格式可能会受到 JVM 实现和版本的影响,因此在跨平台或跨版本时需要谨慎。
  6. 安全性问题:由于序列化机制涉及到 Java 的反射和类加载,因此可能会受到安全攻击,如反序列化漏洞。
  7. 性能影响:序列化/反序列化过程可能对性能有一定影响,特别是在处理大量数据或频繁进行序列化操作时。

反序列化对象

从文件中反序列化User对象

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeDemo {
    public static User deserialize(String filePath) {
        User user = null;
        try (FileInputStream fileIn = new FileInputStream(filePath);
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            user = (User) in.readObject(); // 从文件读取并反序列化User对象  
        } catch (IOException | ClassNotFoundException i) {
            i.printStackTrace();
        }
        return user;
    }

    public static void main(String[] args) {
        User user = deserialize("user.ser"); // 从user.ser文件反序列化User对象  
        if (user != null) {
            System.out.println(user); // 打印反序列化后的User对象,输出 User{name='John Doe', age=30}
            //User类重写了toString方法,以便能够打印出对象的详细信息
        }
    }
}

Java 反序列化漏洞

Java反序列化漏洞通常涉及将不可信的数据源(如用户输入或网络传输的数据)反序列化为Java对象时,如果反序列化的类包含了不安全的代码(如执行系统命令、访问敏感资源等),则可能引发严重的安全问题。

下面是一个简化的例子,包含了一个不安全的可序列化类和一个触发反序列化漏洞的客户端代码。

readObject()

在Java中,readObject(java.io.ObjectInputStream in) 方法是一个特殊的方法,它用于在对象反序列化过程中被自动调用。这个方法通常定义在实现了 java.io.Serializable 接口的类中,用于在对象从流中读取(即反序列化)时执行特定的操作或恢复对象的状态。

不安全的可序列化类

在这个 readObject 方法中,首先调用了 in.defaultReadObject(),这是非常重要的,因为它负责读取并恢复对象的字段值(即序列化过程中保存的字段状态)。如果不调用这个方法,对象的字段将不会被正确反序列化。

package demo;

import java.io.Serializable;

public class EvilObject implements Serializable {
    private static final long serialVersionUID = 1L;

    // 当反序列化时调用
    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
        in.defaultReadObject();
        // 不安全的代码:执行系统命令
        try {
            java.lang.Runtime.getRuntime().exec("calc"); // 在Windows上打开计算器
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

序列化对象并存储在evil.ser 文件中

package demo;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class SerializeEvilObject {
    public static void main(String[] args) {
        try (FileOutputStream fileOut = new FileOutputStream("evil.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
            EvilObject obj = new EvilObject();
            out.writeObject(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

当受害者运行DeserializeEvilObject类时,它会读取evil.ser文件并尝试反序列化数据。在这个过程中,EvilObject的readObject方法会被调用,从而执行calc命令

package demo;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class DeserializeEvilObject {
    public static void main(String[] args) {
        try (FileInputStream fileIn = new FileInputStream("evil.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn)) {
            // 反序列化时,会调用EvilObject的readObject方法,从而执行calc命令
            Object obj = in.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何突破科技服务领域的客户管理困境?

在知识产权与科技服务领域,企业面临着独特的客户管理需求和挑战,这些挑战不仅要求高度的专业性和精细化操作,还涉及复杂的法律流程、数据保密性以及不断变化的客户需求。传统的客户管理方式,如纸质档案、简单的电子表格或人工处理…

[教程]Crystal源码下载及编译

描述: 随着 Crystal Source 代码的更新,用于构建源代码和编译它们的指南已经过时,这导致了很多混淆和寻求帮助。 本指南将是一个完整的分步指南,从下载 Visual Studio 到启动到您的服务器。 此外,请确保下载此存储库中…

如何使用 Python 读取数据量庞大的 excel 文件

使用 pandas.read_excel 读取大文件时,的确会遇到性能瓶颈,特别是对于10万行20列这种规模的 .xlsx 文件,常规的 pandas 方法可能会比较慢。 要提高读取速度,关键是找到更高效的方式处理 Excel 文件,特别是在 Python 的…

Docker版MKVtoolnix的安装及中文显示

本文是应网友 kkkhi 要求折腾的,只研究了 MKVtoolnix 的安装及中文显示,未涉及到软件的使用; 什么是 MKVtoolnix ? MKVToolnix 是一款功能强大的多媒体处理工具,用于在 Linux、其他 Unix 系统和 Windows 上创建、修改和…

uniapp/vue项目 import 导入文件时提示Module is not installed,‘@/views/xxx‘路径无法追踪

文章目录 背景解决方案1.IDE配置2.alias(别名)配置webpackvue-clivite 3.检查 jsconfig.json 或 tsconfig.json 写在最后 前往闪闪の小窝以获得更好的阅读和评论体验 背景 Vue3在我自学Vue的时候看过一点,实操过一点,但是太久没用…

css 下拉框展示:当hover的时候展示下拉框 z-index的用法解释

代码如下&#xff1a; <template><div class"outer"><div class"left"></div><div class"aTest2"><div class"box">显示方框</div><div class"aTest3"></div></…

2024年度全球前2%顶尖科学家榜单发布!大陆10687人上榜,占比仅4.92%,附大陆Top 1000榜单!

9月16日&#xff0c;美国斯坦福大学的John Ioannidis教授团队新近在爱思唯尔(Elsevier)出版集团官网上发布了2024年全球各学科前2%科学家榜单(第七版)&#xff0c;通过统计每个科学家发表的论文数及其引用次数&#xff0c;采用6种指标建模进行综合评分(模型和指标附后)&#xf…

MIC麦克风工作原理:【图片+公式计算讲解】

Mic一个声电传换装置&#xff0c;广泛应用于电子产品中&#xff0c;最常见的就是手机。我们通常也叫它送话器&#xff0c;今天我们就来好好学习一下Mic的电路和它的工作原理。 1&#xff1a;电路结构图 1&#xff1a;C&#xff1a;Mic的核心部件&#xff0c;是一个可以膜片震动…

Linux之Docker虚拟化部署

上传docker安装包 解压安装包 将解压后的docker文件夹移动到/usr/local/文件夹下 docker 启动命令/usr/local/docker/dockerd 但是启动报错&#xff0c;意思是没有docker用户组 创建docker用户组&#xff0c;执行完会生成套接字文件 将套接字文件加入该用户组管理 第二个错误原…

【Lcode 随笔】C语言版看了不后悔系列持续更新中。。。

文章目录 题目一&#xff1a;最长回文子串题目描述&#xff1a;示例输入与输出&#xff1a;题目分析&#xff1a;解题思路&#xff1a;示例代码&#xff1a;深入剖析&#xff1a; 题目二&#xff1a;合并K个有序链表题目描述&#xff1a;示例输入与输出&#xff1a;题目分析&am…

k8s中,ingress的实现原理,及其架构。

图片来源&#xff1a;自己画的 图片来源&#xff1a;k8s官网 首先&#xff0c;什么是ingress? 是服务还是控制器&#xff1f; 都不精确 ingress是一个api资源 service和deployment也是api资源。 这几个相互协作&#xff0c;组建成一个对外提供服务的架构。 ingress提供的…

java学习-idea编辑器基础使用设置

首先打开电脑中的idea编辑器&#xff0c;点击头部&#xff1a;File按钮 → Settings… 打开设置界面&#xff1b; 设置idea的主题 设置idea代码注释的字体颜色 设置idea编辑器的字体和字体大小 设置idea通过提示回车自动导入包 设置idea输入忽略大小写进行提示

计算机网络面试题——第二篇

1. TCP拆包和粘包 现象 粘包&#xff1a;指在TCP传输中&#xff0c;发送方的多个数据包在接收方被合并在一个包接收&#xff0c;导致多条消息数据粘在一起&#xff0c;接收方无法正确区分这些消息的边界。拆包&#xff1a;指的是发送方的一个数据包在接收方被分成了多个包接收…

CHARLS数据库系列教程(4)--多模型效应分析、Per SD、P for trend及限制立方样条图绘制

CHARLS 是一项具备中国大陆 45 岁及以上人群代表性的追踪调查&#xff0c;旨在建设一个高质量的公共微观数据库&#xff0c;采集的信息涵盖社会经济状况和健康状况等多维度的信息&#xff0c;以满足老龄科学研究的需要。 为利用国际上最佳的数据采集方式&#xff0c;并确保研究…

shinyproxy部署streamlit记录

shinyproxy部署streamlit记录 streamlit 也是构建shinyproxy的后段是docker&#xff0c;所以不但可以部署shiny应用&#xff0c;还可以部署streamlit应用以及其它的应用程序。 部署的过程分两步&#xff0c;第一步是构建streamlit应用的docker镜像&#xff0c;就是构建Docker…

Linux高级编程_26_shell

文章目录 shell概述:分类&#xff1a;语法&#xff1a;1、#&#xff01;2、#3、执行&#xff1a;方式1&#xff1a;方式2&#xff1a;方式3&#xff1a; 注意&#xff1a; 第一个shell脚本变量变量的定义&#xff1a;变量的修改变量的取值撤销变量声明只读变量导出变量&#xf…

【HDP】zookeeper未授权漏洞修复

目录 一、禁用四字命令 二、ZK-Client增加kerberos 一、禁用四字命令 Zookeeper四字命令的使用方式非常简单&#xff0c;通常有两种方式。第一种是通过Telnet方式&#xff0c;使用Telnet客户端登录ZooKeeper的对外服务端口&#xff0c;然后直接使用四字命令即可&#xff1b;第…

Kafka快速实战与基本原理详解

笔记:https://note.youdao.com/ynoteshare/index.html?id=b0357bdb4821ed2e35ecdbdacd65aa06&type=note&_time=1727570043631 启动kafka之前先启动zookper 看看ZK里面都有什么数据 : 刚开始什么数据都没有 接下来启动kafka,启动好后,日志在这里看: 启动好了kaf…

处于风口期的本地生活服务项目有哪些?如何入局才能赚得更多?

随着多家互联网大厂在本地生活服务板块的投入力度不断加大&#xff0c;越来越多的人都养成了在其本地生活服务板块消费的习惯&#xff0c;令各大平台本地生活业务日渐兴盛的同时&#xff0c;也让许多创业者发现了本地生活服务赛道中所蕴含着的商机&#xff0c;本地生活服务项目…

苏州 数字化科技展厅展馆-「世岩科技」一站式服务商

数字化科技展厅展馆设计施工是一个综合性强、技术要求高的项目&#xff0c;涉及到众多方面的要点。以下是对数字化科技展厅展馆设计施工要点的详细分析&#xff1a; 一、明确目标与定位 在设计之初&#xff0c;必须明确展厅的目标和定位。这包括确定展厅的主题、目标受众、展…