关注我们

ThinkPHP5.0.x反序列化利用链

yjc123yjc123 安全文摘 2020-01-16 14148 0

漏洞环境

漏洞测试环境:PHP5.6+Linux+ThinkPHP5.0.24

漏洞测试代码 application/index/controller/Index.php 。

<?phpnamespace app\index\controller;class Index{
    public function index()
    {
        $c = unserialize($_GET['c']);
        var_dump($c);
        return 'Welcome to thinkphp5.0.24';
    }}

漏洞分析

POP 链入口点为 think\process\pipes:__destruct 方法。通过 __destruct 方法里调用的 removeFiles 方法,可以利用 file_exists 函数来触发任意类的 __toString 方法,这里我们选择 think\Model 类来触发。由于该类为抽象类,所以我们后续在构造 EXP 的时候得使用其子类,例如: think\Model\Pivot 类。

ThinkPHP5.0.x反序列化利用链

在先前的 ThinkPHP5.1.X 反序列化链中,都是在调用 think\Model:toArray() 时触发 think\Request:__call() 。然而 ThinkPHP5.0.X 中的 think\Request:__call() 写法与 ThinkPHP5.1.X 的不一样了,因为成员变量不可控。

ThinkPHP5.0.x反序列化利用链

所以我们需要找其他可利用的 __call 方法,这里我们选择 think\console\Output 类。其 __call 方法最终会调用到 $this->handle->write() ,而这个 $this->handle 可控,所以思路就是找一个类的 write 方法可以实现写文件。

ThinkPHP5.0.x反序列化利用链

这里,我们将 think\console\Output 类的 handler 属性设置成 think\session\driver\Memcached 类对象。因为我们发现 think\cache\driver\File:set() 方法可以写文件,刚好 think\session\driver\Memcached:write() 中调用了 set 方法,且又有一个可控的 handler 属性。我们继续深入,看看如何利用 think\cache\driver\File:set() 方法写文件。

首先, $filename 的前一部分 $this->options['path'] 可控,但是这时的 $value=true ,其在 think\console\Output:writeln() 方法中固定为 true ,也就是说下图第158行写入文件的代码我们不可控。但是我们继续往下看,发现 $this->setTagItem($filename) 中又调用了 set 方法写文件,而此时传入的 $value为我们部分可控的 $filename 。那么此时,我们就可以使用 PHP 的伪协议来写 shell 。

ThinkPHP5.0.x反序列化利用链

例如,我们将部分可控的 $this->options['path'] 设置成 php://filter/write=string.rot13/resource=<?cuc @riny($_TRG[_]);?> ,最后就会生成一个一句话木马(访问 webshell 的时候,注意要将文件名中的 ? 号 URL编码 成 %3f )。

ThinkPHP5.0.x反序列化利用链

后面的利用基本讲完了,我们再回到刚刚的 think\Model:toArray() ,因为我们还没说明选择何处调用 __call方法。这里我们选择通过下图第912行的 $value->getAttr() ,来触发 think\console\Output:__call() 方法。

ThinkPHP5.0.x反序列化利用链

那么这里的 $value 一定是 think\console\Output 类对象,其在上图第902行 $this->getRelationData($modelRelation) 被赋值。其中,参数 $modelRelation = $this->$relation() ,实际上就是 think\Model 类任意方法的返回结果。这里我选择返回结果简单可控的 getError 方法。

ThinkPHP5.0.x反序列化利用链

参数已经可控了,接下来我们就直接看 think\Model:getRelationData() 的具体代码。下图的 $this->parent肯定是 think\console\Output 类对象,所以我们只需要满足下面的 if 语句即可。这里我们 think\model\Relation 类的 isSelfRelation、getModel 方法返回值都可控,所以我们找 think\model\Relation 的子类套一下即可。

ThinkPHP5.0.x反序列化利用链

万一网站不允许写文件,我们可以稍微修改下 payload 用于创建一个 0755 权限的目录(这里利用的是 think\cache\driver\File:getCacheKey() 中的 mkdir 函数),然后再往这个目录写文件。

ThinkPHP5.0.x反序列化利用链

最终生成 shell 的 EXP 如下:

已删除

参考

ThinkPHP v5.0.x 反序列化利用链挖掘

文由先知社区

版权声明

本文仅代表作者观点,不代表黑白网立场。
如文章侵犯了您的权利,请通过邮箱联系我们删除。
详情查看:版权纠纷
E-Mail:server@heibai.org

喜欢0发布评论

评论列表

发表评论

  • 昵称(必填)
  • 邮箱
  • 网址