java安全(五)java反序列化

给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!

在这里插入图片描述

1. 序列化

在调用RMI时,发现接收发送数据都是反序列化数据.

例如JSON和XML等语言,在网络上传递信息,都会用到一些格式化数据,大多数处理方法中,JSON和XML支持的数据类型就是基本数据类型,整型、浮点型、字符串、布尔等,如果开发者希望在传输数据的时候直接传输一个对象,那么就不得不想办法扩展基础的JSON(XML)语法。比如,Jackson和Fastjson这类序列化库,在JSON(XML)的基础上进行改造,通过特定的语法来传递对象.

RMI使用java等语言内置的序列化方法,将一个对象转化成一串二进制数据进行传输

2.反序列化

不管是Jackson、Fastjson还是编程语言内置的序列化方法,一旦涉及到序列化与反序列化数据,就可能会涉及到安全问题。但首先要理解的是,“反序列化漏洞”是对一类漏洞的泛指,而不是专指某种反序列化方法导致的漏洞,比如Jackson反序列化漏洞和Java readObject造成的反序列化漏洞就是完全不同的两种漏洞。

在Java中实现对象反序列化非常简单,实现java.io.Serializable(内部序列化)java.io.Externalizable(外部序列化)接口即可被序列化,其中java.io.Externalizable接口只是实现了java.io.Serializable接口。

反序列化类对象时有如下限制:
1.被反序列化的类必须存在。
2. serialVersionUID值必须一致。

除此之外,反序列化类对象是不会调用该类构造方法的,因为在反序列化创建类实例时使用了sun.reflect.ReflectionFactory.newConstructorForSerialization创建了一个反序列化专用的Constructor(反射构造方法对象),使用这个特殊的Constructor可以绕过构造方法创建类实例(前面章节讲sun.misc.Unsafe 的时候我们提到了使用allocateInstance方法也可以实现绕过构造方法创建类实例)。

3.反序列化方法的对比

在接触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 更倾向于解决“反序列化后如何初始化这个对象”的
问题。

4.PHP反序列化

PHP的序列化是开发者不能参与的,开发者调用 serialize 函数后,序列化的数据就已经完成了,你得到的是一个完整的对象,你并不能在序列化数据流里新增某一个内容,你如果想插入新的内容,只有将其保存在一个属性中。也就是说PHP的序列化、反序列化是一个纯内部的过程,而其 __sleep 、 __wakeup 魔术方法的目的就是在序列化、反序列化的前后执行一些操作。

一个非常典型的PHP序列化例子,就是含有资源类型的PHP类,如数据库连接:

<?php 
class Connection 
{
    
protected $link; 
private $dsn, $username, $password; 
public function __construct($dsn, $username, $password) 
{
    
$this->dsn = $dsn; 
$this->username = $username; 
$this->password = $password; 
$this->connect(); 
}
private function connect() 
{
    
$this->link = new PDO($this->dsn, $this->username, $this- 
>password); 
} 
} 

PHP中,资源类型的对象默认是不会写入序列化数据中的。那么上述Connection类的 $link 属性在序
列化后就是null,反序列化时拿到的也是null。
那么,如果我想要反序列化时拿到的 $link 就是一个数据库连接,我就需要编写 __wakeup 方法:

<?php 
class Connection 
{
    
protected $link; 
private $dsn, $username, $password; 
public function __construct($dsn, $username, $password) 
{
    
$this->dsn = $dsn; 
$this->username = $username; 
$this->password = $password; 
$this->connect(); 
}
private function connect() 
{
    
$this->link = new PDO($this->dsn, $this->username, $this- 
>password); 
}
public function __sleep() 
{
    
return array('dsn', 'username', 'password'); 
}
public 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

b1gpig安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值