1.前言
最近有点闲下来了,不找点事干比较难受,打算找点漏洞分析一下,于是就打算看看TP的一些漏洞,ThinkPHP6.0.13是TP的最新版,八月份有师傅提交了一个issue指出TP存在反序列化问题,网上也有些师傅分析了一波,不过断点下的比较多,而且部分方法没有阐明其用途,所以我也尝试详细的分析一波。下面先给出POC
2.分析
首先看看POC的起始点
发现起始点在Psr6Cache这个类,我们进入这个类,不过没有发现__destruct或者__wakeup等常见的反序列化起始魔术方法,推测应该在其父类AbstractCache这个抽象类中。跟入AbstractCache类
如图,成功发现本次反序列化链子的起始类。这里我们可以控制autosave这个属性为false,从而进入save方法。
①网安学习成长路径思维导图
②60+网安经典常用工具包
③+SRC漏洞分析报告
④+网安攻防实战技术电子书
⑤最权威CISSP认证考试指南+题库
⑥超页CTF实战技巧手册
⑦最新网安大厂面试题合集(含答案)
⑧APP客户端安全检测指南(安卓+IOS)
回到Psr6Cache类查看这个方法
可以发现,pool属性和key属性我们都可控。因此可能存在两种路线,调用不同类的同名方法(getItem)。或者是直接尝试触发__call方法。我们来看看POC作者是怎么让反序列化进行下去的。
作者用构造方法传入了exp,exp其实就是在实例化Channel类。我们进入Channel类查看
Channel类中有一个__call方法,那么作者是选择触发__call来让链子继续下去。这个call方法接受了两个参数,method是写死的(getItem),parameters是可控的(即前面可控的key属性)
跟入log方法查看,其接受三个传参(但是其实对后续的链子没啥用),传入record方法
跟入record方法
再返回查看作者的POC,发现其控制lazy属性为false,让函数进入最后一个if分支执行save方法
那么save方法应该是比较关键的方法了,跟入save方法,这里面有三个可能被利用的点,作者选择了哪一个呢?
根据POC不难发现作者选择了控制logger属性,利用构造函数对其赋值,令其为Socket类的对象
在这个类中,我们找到了一个复杂的同名方法,其中有大量的操作。
我们继续来看作者是怎么构造的,作者控制config属性,给其赋值为数组。数组有如下内容
关键在于这两个键值,作者控制config,让程序运行到调用invoke方法的分支
同时,app属性可控,作者令app属性为App类的对象,我们进入App类
这里先看看App类的的exists方法的情况,在其父类中找到了这个方法
继续往后,这里对App类进行了唯一一个操作,控制了instances属性的值。这里控制其值是为了进入Request类,并且执行url方法
作者在这里对Request类做出唯一的操纵,就是控制url属性的值。可以看出,如果url属性存在,那么就会进入第一个分支,其值等于本身。
同时又注意到,