PHP反序列化
序列化原理
序列化是指将对象信息转换为可存储或可传输的过程
序列化之后的对应关系:
布尔:b:value
整数:i:value
字符串:s:length:"value"
数组:a:<length>:{key,value paris}
对象:O:<class_name_length>:
NULL:N
最终格式
<class_name>:<number_of_properties>:{<properties>}
例如下面一个序列化例子
class persion
{
public $name;
public $age=19;
public $sex;
}
serialize()序列化之后:
O:6:"persion":3:{s:4:"name";N;s:3:"age";i:19;s:3:"sex";N;}
对象:对象名长度:对象名:属性数:{字符串:长度:名字;属性为空;字符串:长度:名字;整数:值;字符串:长度:名字;空;}
利用反序列化漏洞的条件:
- unserialize函数的参数可控
- php中有可以利用的类并类中有魔术方法
常见魔术方法:
_construst:对象创建
_destrust:对象销毁
_toString:对象被当做一个字符串使用
_sleep:序列化对象前调用(返回一个数组
_wakeup:反序列化恢复对象前调用
_call:调用对象中不存在的方法时自动调用
_get:从不可访问的属性读取数据
技巧
_wakeup失效: PHP5-5.6.25,PHP7.-7.0.10
当属性的个数不正确的时候,PHP不会调用__wakeup
bypass反序列化正则:使用正则/[oc]:\d+:/i
来过滤反序列化字符,可以在O字段的对象长度前面加个+来绕过
Exception绕过:假设某类B,其flag在__desturct中,但因为后面又throw导致__destruct不会执行,这是构造属性为O:1:"B":1{1}
,解析错误但是类名是对的,所以会调用该类的__desturct
例
index.php
<?php
class SoFun{
public $file='index.php';
function __destruct(){
if(!empty($this->file)){
if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false){
echo "<br>";
show_source(dirname (__FILE__).'/'.$this ->file);}
else
die('Wrong filename.');
}
}
function __wakeup(){
$this-> file='index.php';
}
public function __toString(){return '' ;}}
if (!isset($_GET['file'])){
show_source('index.php');
}
else
{
$file = $_GET['file'];
echo unserialize($file);
}
?> <!--key in flag.php-->
在flag.php里面有flag,但是因为wakeup函数的问题,他在反序列化的时候回把file名自动赋值为index.php,这时利用__wakeup()函数的漏洞,即输入错误的属性数,可以导致其不会运行,从而代入flag.php来获取最后的结果
评论已关闭