一、什么是反序列化
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
序列化的实现方法:
- 把一个Java对象写入到硬盘、数据库、文件中,或者传输到网路上面的其它计算机,这时我们就需要自己去通过java把相应的对象转换成字节流。
- 在Java的OutputStream类下面的子类ObjectOutputStream类就有对应的WriteObject(Object object)其中要求对应的object实现了iava的序列化的接口。
反序列化
- 将字节流(二进制数据)换回原对象
- 构造方法:ObjectInputStream(InputStream in)
- 方法:Object readObject(),从 ObjectInputStream 读取对象
通俗的说,就是现在流行面向对象开发,万物皆对象。比如一个student对象有着很多属性,我们在用的时候可以这么赋值,以PHP为例一个stu对象,有很多属性,name,sex等等,是json格式,如下:
$stu1 = new Stu();$stu1->name=“GGG'$stu1->sex= true;$stu1->age = 18;$stu1->score = 89.9; |
这样的数据,很占空间,所以在临时存储时,会序列化成一种便于存储的字符串格式,如:Array{ “name":"GGG",“age” :18,“SEX” :true,“score” :89.9}。这样用的时候,再序列化回来,使用serialize()和unserialize()函数来来回回转这就是序列化和反序列化。
序列化通常被用于:
- 远程通信和进程间通信(RPC/IPC)
- 连线协议、Web服务、消息代理
- 缓存/持久性
- 数据库、缓存服务器、文件系统
- HTTP cookie、HTML表单参数、API身份验证令牌
二、不安全的反序列化
对反序列化的利用是有点困难的,因为在不更改或调整底层可被利用代码的情况下,现成的反序列化漏洞很难被使用。
这一问题包括在Top 10的行业调查中,而不是基于可量化的数据。
有些工具可以被用于发现反序列化缺陷,但经常需要人工帮助来验证发现的问题。希望有关反序列化缺陷的普遍性数据将随着工具的开发而被更多的识别和解决。
反序列化缺陷的影响不能被低估。它们可能导致远程代码执行攻击,这是可能发生的最严重的攻击之一。业务影响取决于应用程序和数据的保护需求。
1. 漏洞产生的原因
序列化和反序列化本身并不存在问题,但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中,执行构造的任意代码漏洞代码。
示例如下:
//读取输入流,并转换对象InputStream in=request.getlnputStream();ObjectlnputStream ois = new ObjectlnputStream(in)://恢复对象ois.readObject();ois.close(); |
2. 漏洞产生的影响
可能导致两种主要类型的攻击:
- 与对象和数据结构相关的攻击,如果应用程序中存在可在反序列化期间,或之后更改行为的类,则攻击者可以修改应用程序逻辑或实现任意远程代码执行。
- 典型的数据篡改攻击,例如使用现有数据结构但内容发生该改变的访问控制相关攻击
反序列化缺陷还可能导致拒绝服务、访问控制攻击。
3. 如何防御?
唯一安全的架构模式是不接受来自不受信源的序列化对象,也不使用只允许原始数据类型的序列化介质。如果做不到以上要求,可以考虑使用下述方法——
- 执行完整性检查,如: 在序列化对象上实现完整性检查,例如数字签名,以防止恶意对象创建或数据篡改。
- 在对象创建之前的反序列化期间强制执行严格的类型约束,因为代码通常需要一组可定义的类。
- 隔离运行在低特权环境中反序列化的代码。
- 记录反序列化的异常情况和失败信息,如: 传入的类型不是预期的类型,或者反序列处理引发的例外情况。
- 限制或监视来自于容器或服务器传入和传出的反序列化网络连接。
- 监控反序列化,当用户持续进行反序列化时,对用户进行警告。