漏洞简介
TP6删除了Windows类,但是可以通过Model类的__destruct()方法触发save函数,在checkAllowFields方法中存在$this->table与$this->suffix的拼接,触发__toString()方法,最后实现$closure的动态调用
配置
1 | composer create-project --prefer-dist topthink/think=6.0.x-dev tp6x |
将 application/index/controller/Index.php 代码修改成如下:
1 |
|
漏洞演示
利用条件
- 存在反序列化点
- 存在phar反序列化
以上满足一个即可
poc.php
1 |
|

漏洞分析
漏洞的起始点在Model类中的__destruct方法,然后进入save方法,此处的$this->exists需要为true进入到updatedata方法

需要调用checkAllowFields方法,需要通过false === $this->trigger('BeforeUpdate')条件判断,那么只需要将withEvent设置为false即可

可以看到checkAllowFields方法中$this->table和$this->suffix进行了拼接,会触发__toString()函数

上半部分分析完成,链子如下
1 | # Model.php |
在Conversion中调用__toString()=>toJson()=>toArray(),最终进入到elseif的第二个分支的getAttr方法,key为$this->data的键

通过getAttr=>getData=>getFieldName最终返回的$value是$this->data[$key],然后进入getValue方法

从$this->withAttr获取$FieldName变量为$closure作为调用函数,从$this->data获取$FieldName变量为调用参数$value,那么只需要令$this->withAttr[$FieldName]为system,$this->data[$FieldName]为参数,即可执行系统命令

漏洞分析至此结束
漏洞修复
增加了对$closure变量的验证再调用
