Java序列化反序列化原理及漏洞解决方案

Java序列化

Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

Java反序列化

反序列化就是将字节序列恢复为Java对象的过程

整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象,因此可以实现多平台之间的通信、对象持久化存储,主要有如下几个应用场景。

HTTP:多平台之间的通信,管理等

RMI:是 Java 的一组拥护开发分布式应用程序的 API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是1099端口。

JMX:JMX 是一套标准的代理和服务,用户可以在任何 Java 应用程序中使用这些代理和服务实现管理,中间件软件 WebLogic 的管理页面就是基于 JMX 开发的,而 JBoss 则整个系统都基于 JMX 构架。

系列化反序列化基础

序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。

一个类的对象能够序列化的成功需要两个条件

  • 该类必须实现 java.io.Serializable 接口
  • 该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。

漏洞基本原理

简单的反序列化Demo

首先定义对象类Persion,包含两个参数

public class implements java.io.Serializable{
  public String name;
  public int age;
  public void info(){
    System.out.println("Name:"+this.name+";nAge:"+this.age);
  }
}

在主类中声明对象,并且将对象序列化为二进制文件,将其存储到硬盘中

import java.io.*;

public class Main{
  public static void main(String [] args){
    将对象序列化为二进制文件
    Persion p = new Persion();
    p.name = "Joner";
    p.age = 18;
    try {

      //打开一个文件输入流
      FileOutputStream fileOut = new FileOutputStream("D:\test\test.db");
      //建立对象输入流
      ObjectOutputStream out = new ObjectOutputStream(fileOut);
      //输出反序列化对象
      out.writeObject(p);
      out.close();
      fileOut.close();
      System.out.printf("保存成功");
    }catch(IOException i){
      i.printStackTrace();
    }
}

进行反序列化

import java.io.*;

public class Main{
  public static void main(String [] args){
    /*从二进制文件中提取对象*/
    Persion persion = null;
    try{
      FileInputStream fileInputStream = new FileInputStream("D:\test\test.db");
      //建立对象输入流
      ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
      persion = (Persion) inputStream.readObject();
      inputStream.close();
      fileInputStream.close();
    }catch (ClassNotFoundException c){
      System.out.println("对象未找到");
      c.printStackTrace();
      return;
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return;
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
    System.out.println("反序列化对象.......");
    System.out.println("Name:"+persion.name);
    System.out.println("Age:"+persion.age);
    }
}

查看test.db文件的内容可以看见如下内容

其中 AC ED 00 05 是java 序列化内容的特征,其中00 05 是版本信息,base64编码后为ro0AB

反序列化漏洞Demo

在上面的Demo中可以看到,进行反序列化时会调用readObject()方法,如果readObject方法书写不当就会引发漏洞。

import java.io.*;

public class Main{
  public static void main(String [] args)throws Exception{
    Unsafeclass unsafeclass = new Unsafeclass();
    unsafeclass.name = "hhhhh";
    FileOutputStream fileOutputStream = new FileOutputStream("object");
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
    //将对象写入object文件
    objectOutputStream.writeObject(unsafeclass);
    objectOutputStream.close();

    //从文件中反序列化对象
    FileInputStream fileInputStream = new FileInputStream("object");
    ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
    //恢复对象
    Unsafeclass objectFormDisk = (Unsafeclass)objectInputStream.readObject();
    System.out.println(objectFormDisk.name);
    objectOutputStream.close();
  }
}
class Unsafeclass implements Serializable{
  public String name;
  //重写readObject()方法
  private void readObject(java.io.ObjectInputStream inputStream ) throws IOException , ClassNotFoundException{
    //执行默认的readObdect()方法
    inputStream.defaultReadObject();
    //执行打开计算器命令
    Runtime.getRuntime().exec("calc.exe");
  }
}

程序运行过程为:

  • UnsafeClass类背序列化进入object文件
  • 从object文件中恢复对象
  • 调用被恢复对象的readObject()方法
  • 命令被执行

这样看感觉并不会有人会这样写readobject()这个方法,而且一些成熟的框架都会有防范反序列化的方法,但仍有很大比例的反序列化漏洞,这主要是使用了不安全的库造成的。上面只是介绍了简单的Java反序列化过程,接下来会有一篇文章介绍反序列化漏洞检测方法以及复现一些经典反序列化漏洞。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java原生序列化和反序列化代码实例

    这篇文章主要介绍了Java原生序列化和反序列化代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 写一个Java原生的序列化和反序列化的DEMO. 需序列化的类: package com.nicchagil.nativeserialize; import java.io.Serializable; public class User implements Serializable { private static final long se

  • Java JDBC导致的反序列化攻击原理解析

    这篇文章主要介绍了Java JDBC导致的反序列化攻击原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 背景 上周BlackHat Europe 2019的议题<New Exploit Technique In Java Deserialization Attack>中提到了一个通过注入JDBC URL实现反序列化攻击的场景,简单分析一下. 分析 首先,当java应用使用MySQL Connector/J(官方的JDBC驱动,本文基于其

  • Java 序列化和反序列化实例详解

    Java 序列化和反序列化实例详解 在分布式应用中,对象只有经过序列化才能在各个分布式组件之间传输,这就涉及到两个方面的技术-发送者将对象序列化,接受者将对象反序列化,下面就是一个很好的例子! 1.实体-Employee import java.io.Serializable; public class Employee implements Serializable{ /** * */ private static final long serialVersionUID = 1L; publi

  • Java对象的XML序列化与反序列化实例解析

    上一篇文章我们介绍了java实现的各种排序算法代码示例,本文我们看看Java对象的xml序列化与反序列化的相关内容,具体如下. XML是一种标准的数据交换规范,可以方便地用于在应用之间交换各类数据.如果能在Java对象和XML文档之间建立某种映射,例如Java对象的XML序列化和反序列化,那么就可以使Java的对象方便地与其他应用进行交换. java.beans包里面有两个类XMLEncoder和Decoder,分别用于将符合JabaBeans规范的Java对象以XML方式序列化和反序列化.以下

  • JAVA序列化和反序列化的底层实现原理解析

    一.基本概念 1.什么是序列化和反序列化 (1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: (2)**序列化:**对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性.序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中.序列化后的字节流保存了Java对象的状态以及相关的描述信息.序列化机制的核心作用就是对象状态的保存与重建. (3)**反序列化:**客户端从文件中或网络上获得序列化后

  • Java将对象写入文件读出_序列化与反序列化的实例

    Java类中对象的序列化工作是通过ObjectOutputStream和ObjectInputStream来完成的. 写入: File aFile=new File("e:\\c.txt"); Stu a=new Stu(1, "aa", "1"); FileOutputStream fileOutputStream=null; try { fileOutputStream = new FileOutputStream(aFile); Objec

  • 详解Java 序列化与反序列化(Serialization)

    一.什么是?为什么需要? 序列化(Serialization)是将对象的状态信息转化为可以存储或者传输的形式的过程,反序列化则为其逆过程. 内存的易失性:传输需要:一些应用场景中需要将对象持久化下来,以便在需要的时候进行读取. 二.JDK提供的API java.io.ObjectOutputStream类的 writeObject(Object obj)方法 java.io.ObjectInputStream类的readObject()方法 对于Serializable,如果没有重写 write

  • java中fastjson生成和解析json数据(序列化和反序列化数据)

    本文讲解2点: 1. fastjson生成和解析json数据 (举例:4种常用类型:JavaBean,List<JavaBean>,List<String>,List<Map<String,Object>) 2.通过一个android程序测试fastjson的用法. fastjson简介: Fastjson是一个Java语言编写的高性能功能完善的JSON库.fastjson采用独创的算法,将parse的速度提升到极致,超过所有json库,包括曾经号称最快的jack

  • Java序列化反序列化原理及漏洞解决方案

    Java序列化 Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据.有关对象的类型的信息和存储在对象中数据的类型. Java反序列化 反序列化就是将字节序列恢复为Java对象的过程 整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象,因此可以实现多平台之间的通信.对象持久化存储,主要有如下几个应用场景. HTTP:多平台之间的通信,管理等 RMI:是 Java 的一

  • java对象序列化与反序列化原理解析

    这篇文章主要介绍了java对象序列化与反序列化原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.序列化和反序列化的概念 对象转换为字节序列的过程称为对象的序列化.把字节序列恢复为对象的过程称为对象的反序列化. 二.序列化和反序列化的作用 对象的序列化主要有两种用途: 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中. 在网络上传送对象的字节序列.网络上传输的都是二进制序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内

  • Java序列化机制与原理的深入分析

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一种处理对象序列化的标准机制.在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的.序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端.这就需要有一种可以在

  • 详解PHP序列化和反序列化原理

    0.前言 对象的序列化和反序列化作用就不再赘述,php中序列化的结果是一个php自定义的字符串格式,有点类似json. 我们在任何语言中设计对象的序列化和反序列化都需要解决几个问题 把某个对象序列化之后,序列化的结果有自描述的功能(从序列化的结果中知道这个对象的具体类型, 知道类型还不够,当然还需要知道这个类型所对应具体的值). 序列化时的权限控制,可以自定义序列化字段等,例如golang中的做的就非常方便. 时间性能问题:在某些性能敏感的场景下,对象序列化就不能拖后腿,例如:高性能服务(我经常

  • java序列化与反序列化的使用方法汇总

    一.概念 java对象序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象.对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一种序列化的形式用于存储和传输.反序列化就是根据这些保存的信息重建对象的过程. 序列化:将java对象转化为字节序列的过程. 反序列化:将字节序列转化为java对象的过程. 二.为什么要序列化和反序列化 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本.图片.音频.视频等, 而这些数据都会以二进制序列的形

  • Java序列化原理详解

    前言 关于序列化的几种疑问? 什么是序列化?工作中什么时候用到序列化了? 为什么实现了java.io.Serializable接口就能序列化? java中serialVersionUID 为什么不能改变? Serializable序列化和json序列化有什么关系? 你都会哪几种对象深拷贝方式? 以上抛出了几个问题,大家都能回答上来吗?回答不上来的话就接着往下看吧. 前提知识: 讲解之前先扩充一些前提知识. 二进制协议和文本协议 首先我们要知道所有的数据在底层的传输都是二进制流,这点是毋庸置疑的.

  • java 序列化与反序列化的实例详解

     1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程.  2.为什么需要序列化与反序列化 我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本.图片.音频.视频等, 而这些数据都会以二进制序列的形式在网络上传送.那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的.如何做到呢?这就需要Java序列化与反序列化了.换句话说,一方面,发送方需要把这个Java对象转换为字

  • java序列化与反序列化操作实例分析

    本文实例分析了java序列化与反序列化操作.分享给大家供大家参考,具体如下: 概述: Java序列化是指把Java对象转换为字节序列的过程;而Java反序列化是指把字节序列恢复为Java对象的过程. 示例代码: import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.i

随机推荐