关于Java解序列化

本文是IBM developerWorks中的一篇文章,介绍了不使用加密与签章技术,如何防止对不可信数据输入的解序列化。(2013.01.18最后更新)

Java序列化允许开发者将Java对象保存为二进制格式,以便将该对象持久化到一个文件中或将其在网络中进行传递。远程方法调用(RMI)使用序列化作为客户端与服务器端之间的通信媒介。当服务从客户端接收二进制数据,以及将输入的数据进行解序列化去构造Java实例时,就会产生多种安全问题。本文关注其中一种问题:骇客可能序列化另一个类的实例,并将其传给服务程序。那么服务程序就会解序列化该恶意对象,并很可能将该对象强制转换为服务所期望得到的合法类型,而这将导致异常的发生。然而,该异常对于确保数据安全性则显得太晚了。本文解释了为什么要以及怎样去实现一种安全的序列化。

脆弱的类

你的服务程序不可能反序列化任意类的对象。为什么不能呢?简单的回答是:因为在服务器端的类路径中可能存有被骇客利用的脆弱类。这些类所包含的代码为骇客造就了拒绝服务(DOS)的条件,或者--在极端情况下--会允许骇客注入任意代码。

你可能会相信存在这种攻击的可能性,但考虑到一个典型的服务器端程序的类路径中存在太多的类,不仅包含你自己的代码,还包括Java核心类库,第三方的类库,以及其它的中间件或框架中的类库。另外,在应用程序的生命周期中,类路径可能会被改变,或者为了应对底层运行环境的变化,应用程序的类路径也可能被修改。当试图去利用这样的弱点时,通过传送多个序列化对象,骇客能够将这些操作组合到一块。

我应该强调一下,仅当满足如下条件时,服务才会解序列化一个恶意对象:

1. 恶意对象的类存在于服务器端的类路径中。骇客不可能随便地传递任意类的序列化对象,因为应用服务可能无法加载这个类。

2. 恶意对象的类要么是可序列化的,要么是可外部化的。(即,服务器端的这个类要实现java.io.Serializable或java.io.Externalizable)

另外,通过从序列化流中直接复制数据,在不调用构造器的情况下,解序列化操作就能产生对象树,所以骇客不可能执行序列化对象类的构造器中的Java代码。

但骇客还有其它途径在服务器端去执行代码。无论JVM在何时去解序列化一个对象,都将实现如下三个方法中的一个,都将调用并执行该方法中的代码:

1. 方法readObject(),当标准的序列化机制不适用时,开发者一般就会用到该方法。例如,当需要对transient成员变量进行赋值时。

2. 方法readResolve(),一般用于序列化单例对象。

3. 方法readExternal(),用于外部化对象。

所以,如果在你的类路径中存在着使用上述方法的类,你就必须意识到骇客可能会在远程调用这些方法。此类攻击在过往曾被用于破坏Applet安全沙箱;同样地,相同的攻击技术也可用于服务器端应用。

继续读下去,将会看到如何才能只允许应用服务对其期望的类的对象进行解序列化。

Java序列化二进制格式

一个对象被序列化之后,二进制数据将包含有元数据(指与数据的结构相关的信息,例如类的名称,成员的数量,以及成员的类型),及对象数据本身。我将以一个简单的Bicycle类作为例子,如清单1所示,该类包含三个成员变量(id,name和nbrWheels)以及与之对应的set与get方法。

清单1. Bicycle类

package com.ibm.ba.scg.LookAheadDeserializer;

public class Bicycle implements java.io.Serializable {

    private static final long serialVersionUID = 5754104541168320730L;

    private int id;
    private String name;
    private int nbrWheels;

    public Bicycle(int id, String name, int nbrWheels) {
        this.id = id;
        this.name = name;
        this.nbrWheels = nbrWheels;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public int getNbrWheels() {
        return nbrWheels;
    }

    public void setNbrWheels(int nbrWheels) {
        this.nbrWheels = nbrWheels;
    }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索数据
, 对象
, 方法
, 路径
, public
一个
java序列化详解、java 注解 不序列化、java 序列化注解、java 序列化、java序列化和反序列化,以便于您获取更多的相关知识。

时间: 2024-12-23 03:22:11

关于Java解序列化的相关文章

关于JAVA的序列化问题

问题描述 本人不才,请求各位大神一个问题.首先,如何理解JAVA的序列化?序列化有什么作用?在实际的项目中什么时候用到序列化?还有就是关于JAVA的一个@Transient注解,如果我在一个持久化类中用他标注属性,那么这个属性就不会映射到数据库中了?如何理解序列化,@Transient,映射三者之间的关系!跪求大神详解! 解决方案 解决方案二:我的理解是,序列化就是把整个对象的属性也就是对象在内存中的数据写入一个字节流.至于怎么写,如果是实现Serializable接口就是默认的实现,用@tra

Ajax 的 Java 对象序列化

ajax|对象 如果您正在使用异步 JavaScript 和 XML(Ajax)进行 Java Web 开发,那么您最关心的问题可能就是把数据从服务器传递给客户机.在面向 Java 开发人员的 Ajax 系列的文章中,Philip McCarthy 介绍了 Java 对象序列化的五种方式,并提供了选择最适合应用程序的数据格式和技术所需要的全部信息.本文将侧重于许多 Java Web 开发人员最关心的问题:为客户机生成数据. 多数 Java 开发人员已经把模型-视图-控制器(MVC)模式应用在他们

Ajax 的 Java 对象序列化(1)

ajax|对象 如果您正在使用异步 JavaScript 和 XML(Ajax)进行 Java Web 开发,那么您最关心的问题可能就是把数据从服务器传递给客户机. 在面向 Java 开发人员的 Ajax 系列的文章中,Philip McCarthy 介绍了 Java 对象序列化的五种方式,并提供了选择最适合应用程序的数据格式和技术所需要的全部信息.本文将侧重于许多 Java Web 开发人员最关心的问题:为客户机生成数据. 多数 Java 开发人员已经把模型-视图-控制器(MVC)模式应用在他

java对象序列化学习笔记

java对象|笔记 目前网络上关于对象序列化的文章不少,但是我发现详细叙述用法和原理的文章太少.本人把自己经过经验总结和实际运用中的体会写成的学习笔记贡献给大家.希望能为整个java社区的繁荣做一点事情.    序列化的过程就是对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机.对象序列化功能非常简单.强大,在RMI.Socket.JMS.EJB都有应用.对象序列化问题在网

关于Java对象序列化您不知道的5件事

数年前,当和一个软件团队一起用 Java 语言编写一个应用程序时,我体会 到比一般程序员多知道一点关于 Java 对象序列化的知识所带来的好处. 大约一年前,一个负责管理应用程序所有用户设置的开发人员,决定将用户 设置存储在一个 Hashtable 中,然后将这个 Hashtable 序列化到磁盘,以便持 久化.当用户更改设置时,便重新将 Hashtable 写到磁盘. 这是一个优雅的.开放式的设置系统,但是,当团队决定从 Hashtable 迁移 到 Java Collections 库中的

Java对象序列化使用基础

所谓对象序列化就是将对象的状态转换成字节流,以后可以通过这些值再生成相同状态的对象.这个过程也可以通过网络实现,可以先在Windows机器上创建一个对象,对其序列化,然后通过网络发给一台Unix机器,然后在那里准确无误地重新"装配".像RMI.Socket.JMS.EJB它们中的一种,彼此为什么能够传递Java对象,当然都是对象序列化机制的功劳. Java对象序列化机制一般来讲有两种用途: Java的JavaBeans: Bean的状态信息通常是在设计时配置的,Bean的状态信息必须被

Java利用序列化实现对象深度clone的方法_java

本文实例讲述了Java利用序列化实现对象深度clone的方法.分享给大家供大家参考.具体实现方法如下: ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(obj); ByteArrayInputStream byteIn = new ByteArrayInputStream(by

Java对象序列化/反序列化的注意事项(转)

Java对象序列化     对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久化的,将运行中的对象状态保存下来(最直接的方式就是保存到文件系统中),在需要的时候可以还原,即使是在Java虚拟机退出的情况下.     对象序列化机制是Java内建的一种对象持久化方式,可以很容易实现在JVM中的活动对象与字节数组(流)之间进行转换,使用得Java对象可以被存储,可以被网络

java对象序列化的概念和实现

一 序列化的概念和实现方法 序列化的概念就是把一个Object直接转换成为Byte流写到硬盘或者通过网络进行传播.Java序列化技术可以将一个对象的状态写入一个Byte流里,并且可以从其它地方把该Byte流里的数据读出来,重新构造一个相同的对象.这种机制允许将对象通过网络进行传播,并可以随时把对象持久化到数据库.文件等系统里.Java的序列化机制是RMI.EJB等技术的技术基础.   序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化.可以对流化后的对象进行读写操作,也可将