炒冷饭之ThinkPHP3.2.X RCE漏洞分析
昨天在朋友圈看到某乙方的安全实验室发布了一个ThinkPHP3.2.x RCE漏洞通报,以为TP3.2的版本研究出新的漏洞姿势,刚好记得腾讯的XSRC应该是基于TP3.2的版本进行开发的,于是跟进了这个漏洞。
根据描述说:
标题:ThinkPHP3.2.x_assign方法第一个变量可控=>变量覆盖=>任意文件包含=>RCE 作者:北门-王境泽@玄甲实验室 审稿:梦想小镇-晨星@玄甲实验室 攻击方式:远程 漏洞危害:严重 攻击url: http://x.x.x.x/index.php?m=Home&c=Index&a=index&value[_filename]=.\Application\Runtime\Logs\Home\21_06_30.log 标签:ThinkPHP3.2.3 RCE 变量覆盖 文件包含 代码执行
于是开始对XSRC的源码进行审计:
发现并没有这样写的
于是手工构造了一下:
把$key的变量移除search_key的,变为第一个参数为可控变量。
根据payload发现,这个RCE需要依赖本地文件包含,TP的有个runtime log可以记录错误model到log中,构造比较简单index.php?c=<?php=phpinfo();?>
然后根据payload 继续测试,&value[_filename]=.\Application\Runtime\Logs\Home\21_06_30.log,(LOG修改自己的日期),发现依旧不成功,决定再继续读一遍他的分析,附图直接引用文章上的,已经列出的分析很清晰了
可控变量进入assign方法赋值给$this→tVar变量:
赋值结束后进入display方法中,display方法开始解析并获取模板文件内容,此时模板文件路径和内容为空:
程序进入fetch方法中,传入的参数为空,程序会去根据配置获取默认的模板文件位置(./Application/Home/View/Index/index.html)。之后,系统配置的默认模板引擎为think,所以程序进入else分支,获取$this→tVar变量值赋值给$params,之后进入Hook::listen方法中。l
listen方法处理后,进入exec方法中
进入exec方法中,处理后调用Behavior\ParseTemplateBehavior类中的run方法处理$params这个带有日志文件路径的值。
程序进入run方法中,一系列判断后,进入else分支,调用Think\Template类中的fetch方法对变量$_data(为带有日志文件路径的变量值)进行处理。
进入Think\Template类中的fetch方法,获取缓存文件路径后,进入Storage的load方法中。
跟进到Storage的load方法中,$_filename为之前获取的缓存文件路径,$var则为之前带有_filename=日志文件路径的数组,$vars不为空则使用extract方法的EXTR_OVERWRITE默认描述对变量值进行覆盖,之后include该日志文件路径,造成文件包含。
这个是摘抄分析的原文,这里有个重点是$assign的第一个参数,将会导入TP中,获取$this→tVar变量值赋值给$params
最终被include,文件包含。
然后修改paylload:
成功执行,这个漏洞主要依赖代码的xxx[_filename] 在和同事交流的时候,发现这个洞,其实14年就提处来了,并且乌云已经报告过了,不知道为什么今天又发出来了。。
phith0n之前分析过一个类似的:CodeIgniter框架内核设计缺陷可能导致任意代码执行
https://bugs.leavesongs.com/php/codeigniter%E6%A1%86%E6%9E%B6%E5%86%85%E6%A0%B8%E8%AE%BE%E8%AE%A1%E7%BC%BA%E9%99%B7%E5%8F%AF%E8%83%BD%E5%AF%BC%E8%87%B4%E4%BB%BB%E6%84%8F%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C/
wooyun之前提交的这个:ThinkPHP远程代码执行隐患(需满足特定条件)
https://wooyun.laolisafe.com/bug_detail.php?wybug_id=wooyun-2014-051906
分析的逻辑也都一样,思路不错,可惜是很久之前的,当做是个炒冷饭吧,可以留作一个后门小技巧。
【漏洞通报】ThinkPHP3.2.x RCE漏洞通报
https://mp.weixin.qq.com/s/_4IZe-aZ_3O2PmdQrVbpdQ
注明:本文章无恶意攻击任何厂商并尊重厂商技术实力,应该是漏洞的作者可能也没发现这个是历史漏洞。