0x00 前言
继续分析 thinkphp v6.0.x 反序列化利用链,本来是打算先分析 thinkphp v5.2.x 的利用链的,但是使用composer 安装失败,而且官方又说只能通过composer 来安装 , 网上找了好久没找到解决方法,然后去github上面提交 issue ,官方给的回复 是没有 5.2版本,这个回答确实有点懵。
所以就先来分析 6.0.x 的反序列化利用链。
0x01 分析
thinkphp 6.0 __toString() 后面的利用链和 thinkphp 5.2 是一样的,就是__toString前面不一样,thikphp 6.0 删除了 Windows 类 (但咱也没分析过thinkphp 5.2 😂), 所以这里分__toString() 前面的利用链 和 后面的利用链 两部分来。
0x 1.1 触发__toString()
首先给出这部分利用链:
think\Model -->__destruct()
think\Model -->save()
think\Model -->updataDate()
think\Model -->checkAllowFields()
think\Model -->db()
入口点 是 vendor/topthink/think-orm/src/Model.php 里面的 __destruct() 函数,
设置 $this->lazySave 为 true
就可以调用 $this->save() 。
跟进 save() 函数:
触发点 在 updataDate() 函数,为了进入updataDate() 函数,需要前面的if 判断条件不符合。看看 isEmpty() 和 trigger() 函数:
那么这里我们设置:
trait Attribute 中:
$this->data 为非空
trait ModelEvent 中:
$this->withEvent 为false
abstract class Model 中:
$this->exists 为 true
再跟进updateData() 函数:
我们需要进入checkAllowFields 函数中,就需要不进入 第一个 if (这个和前面添加一样,已经满足,即trait ModelEvent 中 $this->withEvent为false ),还需要 不进入第二个if ,所以我们跟进 getChangeData() 函数,需要这个函数返回非空:
那么这里我们需要设置:
trait Attribute 中:
$this->force 为true (但由于Attribute中没有force 这个属性,我们在use 了Attribute 中的Model 中设置,其实也可以在Attribute 中设置这个force ,是一样的,主要是去Model 中看他的可访问属性是什么 )
$this->data 为非空
然后回到model.php 中再设置
abstract class Model中:
$this-> autoWriteTimestamp 为空
现在就可以调用checkAllowFileds() 函数了,跟进:
我们需要进入 $this->db() ,里面有触发_toString() 的地方
那么我们设置:
abstract class Model 中:
$this->filed 为空
$this->schema 为空
然后跟进 db() 方法:
熟悉的字符串拼接,我们这里只需要设置:
abstract class