Java安全漫谈 - 07.反序列化篇(1)
这是代码审计知识星球中Java安全的第七篇文章。
之前介绍了JMI的一些流程和攻击方法,我们在调试RMI时会发现,其发送、接收的数据都是反序列化数
据。反序列化这个词在安全领域可谓红极一时,不同语言都拥有此类方法,且多少都拥有相关的漏洞。
那么,为什么反序列化常常会带来安全隐患?
一门成熟的语言,如果需要在网络上传递信息,通常会用到一些格式化数据,比如:
JSON
XML
JSON和XML是通用数据交互格式,通常用于不同语言、不同环境下数据的交互,比如前端的JavaScript
通过JSON和后端服务通信、微信服务器通过XML和公众号服务器通信。但这两个数据格式都有一个共
同的问题:不支持复杂的数据类型。
大多数处理方法中,JSON和XML支持的数据类型就是基本数据类型,整型、浮点型、字符串、布尔
等,如果开发者希望在传输数据的时候直接传输一个对象,那么就不得不想办法扩展基础的
JSON(XML)语法。
比如,Jackson和Fastjson这类序列化库,在JSON(XML)的基础上进行改造,通过特定的语法来传递
对象;亦或者如RMI,直接使用Java等语言内置的序列化方法,将一个对象转换成一串二进制数据进行
传输。
不管是Jackson、Fastjson还是编程语言内置的序列化方法,一旦涉及到序列化与反序列化数据,就可
能会涉及到安全问题。但首先要理解的是,“反序列化漏洞”是对一类漏洞的泛指,而不是专指某种反序
列化方法导致的漏洞,比如Jackson反序列化漏洞和Java readObject造成的反序列化漏洞就是完全不同
的两种漏洞。
我们先来说说Java内置的序列化方法readObject,和其有关的漏洞。
反序列化方法的对比
在接触Java反序列化之前,相比大家多少都了解过其他语言的反序列化漏洞,其中极为经典的要数PHP
和Python。
那么,Java的反序列化,究竟和PHP、Python的反序列化有什么异同?
Java的反序列化和PHP的反序列化其实有点类似,他们都只能将一个对象中的属性按照某种特定的格式
生成一段数据流,在反序列化的时候再按照这个格式将属性拿回来,再赋值给新的对象。
但Java相对PHP序列化更深入的地方在于,其提供了更加高级、灵活地方法 writeObject ,允许开发者
在序列化流中插入一些自定义数据,进而在反序列化的时候能够使用 readObject 进行读取。
当然,PHP中也提供了一个魔术方法叫 __wakeup ,在反序列化的时候进行触发。很多人会认为Java的
readObject 和PHP的 __wakeup 类似,但其实不全对,虽然都是在反序列化的时候触发,但他们解决
的问题稍微有些差异。
Java设计 readObject 的思路和PHP的 __wakeup 不同点在于: readObject 倾向于解决“反序列化时如
何还原一个完整对象”这个问题,而PHP的 __wakeup 更倾向于解决“反序列化后如何初始化这个对象”的
问题。
评论0