反序列化漏洞-----(1) 什么是序列化和反序列化和魔法函数

一、基础概念

为什么要序列化 https://blog.csdn.net/xlgen157387/article/details/79840134
什么是序列化 https://blog.csdn.net/u011215133/article/details/51177843

序列化与反序列化是开发过程中不可或缺的一步,简单来说,序列化是将对象转换成字节流的过程,而反序列化的是将字节流恢复成对象的过程。序列化与序列化主要解决的是数据的一致性问题

在这里插入图片描述

序列化 将数据结构或对象转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程

  • 目的

①以某种存储形式使自定义对象持久化;
②将对象从一个地方传递到另一个地方。
③使程序更具维护性。

  • 为什么要序列化

简单来说序列化就是一种用来处理对象流的机制。所谓对象流也就是将对象内容进行流化(I/O)。直接对对象流进行读写操作时会引发一些问题(例如对象引用时的一致性考虑),而序列化机制正是用来解决这些问题的!

反序列化将序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。


二,php的序列化与反序列化

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示(把复杂的数据类型压缩到一个字符串中)。unserialize()函数能够重新把字符串变回php原来的值。
serialize() 序列化

unserialize() 反序列化

【实列1】对字符串和数字序列化

<?php
//对int型序列化
$aa = 111;
var_dump($aa);
echo "<br>";
echo serialize($aa) . "<br>";


//对字符串序列化
$bb = "hello!";
var_dump($bb);
echo "<br>";
echo serialize($bb) ;
?>

int(111)
i:111;
string(6) “hello!”
s:6:“hello!”;

【实列2】对数组序列化

<?php
$name = array('a' => 'tom' ,'b' => 'jack' , 'c' => 'rose');
var_dump($name);

echo "<br>";
$s = serialize($name);  //返回一个包含字节流的字符串
echo $s . "<br>";


var_dump($s);    //查看s的变量类型
//string(62) "a:3:{s:1:"a";s:3:"tom";s:1:"b";s:4:"jack";s:1:"c";s:4:"rose";}"
?>

【序列化前】 array(3) { [“a”]=> string(3) “tom” [“b”]=> string(4) “jack” [“c”]=> string(4) “rose” }
【序列化后】 a:3:{s:1:“a”;s:3:“tom”;s:1:“b”;s:4:“jack”;s:1:“c”;s:4:“rose”;}

☞对返回的字符串的说明
“ 结构类型a为数组:属性(成员)个数 :{ 属性名类型:长度:名称;值类型:长度:值 } ”


👍👍👍【实列3】对对象序列化

注意 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。
.
为什么要序列化

  • 对象无对应的实体,程序结束后自动消失,想要保存则需序列化。

.
怎么就序列化了?

  • 将对象转换为二进制的字符串进行描述

.
序列化函数

  • serialize(对象) 将一个对象转换成一个字符串

  • unserialize(序列化后的字符串) 将字符串还原为一个对象

eg:一个序列化的实列

<?php
class fruit
{
	//定义属性
	public $name;
	public $price;
	public $change;
	
	//定义方法
	public function __construct($name_value,$price_value,$change_value)
	{
		$this->name = $name_value;
		$this->price = $price_value;
		$this->change = $change_value;
	}
	
}

$obj = new fruit("banana",3.7,"+0.3");
echo $obj->name . "<br>";
echo $obj->change . "<br>";

var_dump($obj);
echo "<br>------序列化后-----<br>";
$s = serialize($obj);
echo $s . "<br>";

echo "<br>------反序列化后-----<br>";
$obj2 = unserialize($s);
var_dump($obj2);
echo "<br>" . $obj2->name;
?>

运行结果
banana
+0.3
object(fruit)#1 (3) { [“name”]=> string(6) “banana” [“price”]=> float(3.7) [“change”]=> string(4) “+0.3” }
------序列化后-----
O:5:“fruit”:3:{s:4:“name”;s:6:“banana”;s:5:“price”;d:3.7000000000000002;s:6:“change”;s:4:"+0.3";}
.
------反序列化后-----
object(fruit)#2 (3) { [“name”]=> string(6) “banana” [“price”]=> float(3.7) [“change”]=> string(4) “+0.3” }
banana

O代表结构类型为类:5表示类名长度:类名:属性个数 { 属性名类型:长度:名称 ;值类型:长度:值;}

2.1 php中的部分魔法函数

PHP类中有一种特殊函数体的存在叫魔法函数,magic函数命名是以符号__开头的,比如 __construct, __destruct, __toString, __sleep, __wakeup等等。这些函数在某些情况下会自动调用

①构造函数☞ __construct()

作用: 通常用于初始化对象的属性

自动调用与: 对象创建时自动调用

...........
...........
	public function __construct($name_value,$price_value,$change_value)
	{
		$this->name = $name_value;
		$this->price = $price_value;
		$this->change = $change_value;
	}
	
}

$obj = new fruit("banana",3.7,"+0.3");  //创建对象时自动调用构造函数 
②析构函数☞ __destruct()

自动调用与: 当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。

析构函数无参数

eg:一个实列

<?php
class A
{
	public $name = "is A";
	public function __destruct()
	{
		echo "当前对象已被销毁";
	}
}
//定义一个对象
$obj = new A();
echo "当前对象的name属性为:" . $obj->name . "<br>";

//销毁对象
echo "<br>----销毁对象后----<br>";
unset($obj);

?>

当前对象的name属性为:is A
.
----销毁对象后----
当前对象已被销毁

③对对象的封装时的魔法函数

__get() 外部访问不存在或者=私有属性时调用
__set() 外部访问不存在或者=私有属性时调用

__isset() 在外部检测是否存在某个属性时调用
__unset() 外部销毁某个私有属性时调用时调用

④序列化和反序列化的魔法函数
__sleep()

自动调用时机:序列化时

作用:将允许序列化的对象放在一组数组中返回,序列化时只序列化指定的属性。

<?php
class fruit
{
	//定义属性
	public $name;
	public $price;
	public $change;
	
	//定义方法
	public function __construct($name_value,$price_value,$change_value)
	{
		$this->name = $name_value;
		$this->price = $price_value;
		$this->change = $change_value;
	}
	
	//定义sleep魔术方法
	public function __sleep()
	{
		return ["name"];
	}
}

$obj = new fruit("apple",10,"-0.2");
var_dump($obj);
echo "<br>对象obj的price属性为:" . $obj->price . "<br>";

echo "<br>------序列化后-----<br>";
$s = serialize($obj);
echo $s . "<br>";

echo "<br>------反序列化后-----<br>";
$obj2 = unserialize($s);
var_dump($obj2);
?>

在这里插入图片描述

__wakeup()

自动调用时机:反序列化时

作用:反序列化时修改属性(对重新生成的对象的属性进行修改),或重新建立数据库连接,或执行其它初始化操作。

eg 1 :

<?php
class fruit
{
	//定义属性
	public $name;
	public $price;
	public $change;
	
	//定义方法
	public function __construct($name_value,$price_value,$change_value)
	{
		$this->name = $name_value;
		$this->price = $price_value;
		$this->change = $change_value;
	}
	
	//定义sleep魔术方法
	public function __sleep()
	{
		return ["name"];
	}
	
	//定义wakeup魔术方法
	public function __wakeup()
	{
		$this ->price=20;
	}
}

$obj = new fruit("apple",10,"-0.2");
var_dump($obj);
echo "<br>对象obj的price属性为:" . $obj->price . "<br>";

echo "<br>------序列化后-----<br>";
$s = serialize($obj);
echo $s . "<br>";

echo "<br>------反序列化后-----<br>";
$obj2 = unserialize($s);
var_dump($obj2);
?>

在这里插入图片描述

eg 2 : 重新建立数据库连接

<?php
class Connection 
{
    protected $link;
    private $server, $username, $password, $db;
    
    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }
    
    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }
    
    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }
    
    public function __wakeup()
    {
        $this->connect();
    }
}
?>
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值