本文是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序列化和反序列化,以便于您获取更多的相关知识。