本篇主要是介绍什么是序列化漏洞,对序列化漏洞有个最初的了解。
序列化的概念
当一个对象需要跨文件传递时,或者说为了更加节省空间,通常会对这个对象进行序列化操作,序列化的好处就是将这个对象变成了数据流
serialize()就是将对象转换为序列化的函数,而unserialize()就是将被序列化的对象重新转换为序列化,通过这样的方式,就可以达到节省空间并且跨文件传递
<?php
class People
{
public $age = 0;
public $name = '';
public function printdata()
{
echo "<br />User '.$this->name.' is '.$this->age.' years old.<br />";
}
}
$P =new People();
$P->age=18;
$P->name='zhangsan';
$P->printdata();
echo serialize($P)
?>
在a.php中,有一个People的对象里面是他的两个变量,在经过赋值以及输出变量后进行了序列化操作,最后页面的输出是这样的 O代表Objec对象,6代表这个对象名字长度是6,People是对象名,2是对象中有2个变量,s是string,3是长度,age是变量名,i是int,18是值,后面的也是同理
而unserlize()中如果放的是
O:6:"People":2:{s:3:"age";i:18;s:4:"name";s:8:"zhangsan";}
那么将会把这个序列对象化。这就是序列化的概念
序列化
谈到序列化不得不谈到几个常见的魔法方法
__destruct():
__wakeup():
__invoke():
__call():
__callStatci():
__get():
__set():
__isset():
__unset():
__toString():
__construct():
__sleep():
当一个类中包含有这些方法时,在满足条件后这些方法会自动触发
例如以下的php文件
<?php
class test
{
public $variable = 'BUZZ';
public $variable2 = 'OTHER';
public function printvariable()
{
echo $this->variable.'<br />';
}
public function __construct()
{
echo '__construct'.'<br />';
}
public function __destruct()
{
echo '__destruct'.'<br />';
}
public function __wakeup()
{
echo '__wakeup'.'<br />';
}
public function __sleep()
{
echo '__sleep'.'<br />';
return array('variable','variable2');
}
}
$object = new test();
$serialized = serialize($object);
print 'Serialized:'.$serialized.'<br />';
$object2 = unserialize($serialized);
$object2->printvariable();
?>
最后的页面回显时这样 可以看到_construct()在对象创立时就自动触发了,序列化对象时触发了_sleep(),而在真是的代码中我并没有实际调用它,是它们自己满足条件后而触发的。 在最后也可以看到有两个_destruct被触发了,是因为有两个对象被在脚本结束被销毁了,所以执行了两次
另外php序列化中 protected属性被序列化的时候属性值会变成%00*%00属性名
private属性被序列化的时候属性值会变成%00类名%00属性名
<?php
class T{
private $a='aa';
protected $b=13;
}
$A=new T();
echo serialize($A)
?>
最终序列化样子是 对于这种情况我们需要反序列化的样子为
O:1:"T":2:{s:4:"%00A%00a";s:2:"aa";s:4:"%00*%00b";i:13;}
当发现一个反序列化漏洞时,我们通常会自己构建一个反序列化的payload,然后执行它并绕过关键魔法方法达到注入效果,例如
<?php
class A{
int a=8;
public function _construct(){
echo 'phpinfo()';
}
$A=$_GET['test']
$B=unserialize($A)
?>
如果我们构造这样一个payload
<?php
class A{
public $a=8;
}
$a=new A();
echo serialize($a);
?>
把序列化后结果输入在url上 当1.php中的对象B创造时,里面的_construct就自动触发了,打开了phpinfo(),这是一个最简单的反序列化漏洞的例子
Session反序列化漏洞
php中Session获取资源也是先序列化再储存,当读取时再进行反序列化操作
<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
$_SESSION['name'] = 'spoock';
var_dump($_SESSION);?>
这是一段php代码,再php_serialize引擎下,session序列化的数据为
a:1:{s:4:"name";s:6:"spoock";}
php引擎下为
name|s:6:"spoock";
php_binary引擎下为
names:6:"spoock";
php正常下session的实现是没有问题的,危害主要是程序员的Session使用不当引起的
当网站序列化存储session与反序列化读取session使用的引擎不同时,会导致数据无法正确的反序列化。
|