漏洞起点
起因: 在做 [安洵杯 2019]iamthinking
时发现是 thinkphp6
的反序列化,那么就去复现一下呗。
看了其他大佬的 wp
,上面说 tp6 的反序列化漏洞的后半段利用和 tp5.2.x
是一样的,也就是 __toString
函数上。
第一步相信大家都知道,全局搜索 __destruct
,查找可以利用的点。
选择的标准:
那么有什么选择的标准呢?我是这么想的,就这个版本而言,假定我们先前不知道哪边有漏洞,那么我们在找漏洞的时候可以先看看前几个版本有什么漏洞,有可能它在修好漏洞的时候,又产生了新的漏洞,或者漏洞依然存在,只是利用方式不同罢了,那么借助这个思路我们可以先看看 tp5.2.x
的漏洞产生点,也就是 __toString
函数上。
全局搜索后可以发现在 Conversion.php
中 __toString
往下推会产生一个漏洞。
__toString => toJson => toArray => getAttr => getValue
可以通过可控的属性进行命令执行。
那么我们这边选择 __destruct
的要求就很明显了,一直往下执行直到有地方能够触发 __toString
。
这边选择如下图:
__toString
的触发点为:
save => updateData => checkAllowFields
在 checkAllowFields
中可以看到有一个字符串连接,而这就是 __toString
的触发点。
步骤分析
第一步触发 __toString
我们首先要绕过 save
函数的第一个 if
判断。
isEmpty
函数只需要 $this->data
不为空即可。
tigger
函数中 $this->withEvent
为 false
就行。
然后就是 save
函数的 $this->exists
存在,则进入 updateData()
。
updateData()
函数的第一步和上一步一样。
接着就是 $ data
要存在绕过下面的 if
,也就是 getChangedData
中的 $this->force
为 true
然后就进入了 checkAllowFields
函数,只需要令 $this->table
为 __toString
的类或者其他。
简单记录一下流程:
触发 __toString:
svae():
isEmpty()::