游客发表
ThinkPHP的渗透渗透测试,核心就是渗透找版本漏洞和利用链。国内不少中小型Web系统还在跑3.2和5.0这两个大版本,渗透这两个分支的渗透历史漏洞多到一只手数不过来。我去年扫过一个电商站,渗透首页看着挺新,渗透结果指纹一跑,渗透ThinkPHP 5.0.22,渗透直接上RCE链,渗透五分钟拿shell。渗透
先说最经典的渗透5.0.x RCE。这个漏洞的渗透触发点在Request类的method()方法里,攻击者可以通过构造?渗透s=index/\think\Request/input这类路由,配合filter[]=system这样的渗透参数,让框架把恶意函数当过滤器执行。渗透具体payload长这样:
POST /index.php?s=captcha Content-Type: application/x-www-form-urlencoded _filter[]=phpinfo&_method=__construct&method=get&get[]=phpinfo&server[REQUEST_METHOD]=1 这个链子的本质是变量覆盖加回调滥用。ThinkPHP在处理_method参数时,会动态调用Request::__construct,而构造函数里对filter属性的赋值没有做白名单校验。只要能把filter覆盖成system,再把get或post数据传进去,命令就执行了。
3.2版本的利用更直接。index.php/module/action/param/value这种PATH_INFO模式,配合preg_replace的/e修饰符,可以直接代码执行。虽然PHP 7已经移除了/e,但很多老站还跑在PHP 5.6上,所以这条链子依然有效。我见过一个政府类站点,ThinkPHP 3.2.3加PHP 5.4,?s=/index/index/name/${ @phpinfo()}直接就弹出了phpinfo页面。
日志文件包含是另一个高频利用点。ThinkPHP在调试模式下会把请求信息写入Runtime/Logs/目录,文件名通常是月份_日期.log。攻击者先发一个带PHP代码的请求,比如,让这段代码进日志,然后通过?s=index/\think\Template/display&template=../../Runtime/Logs/22_01_2024.log这样的路径去包含它。这个手法在5.0和5.1上都验证过,成功率取决于目录权限和文件名猜测。
ThinkPHP 5.1的RCE利用链稍微绕一点。核心是think\process\pipes\Windows类的__destruct方法,配合think\model\concern\Conversion的__toString,构造反序列化POP链。不过5.1的漏洞需要能控制反序列化入口,通常结合phar://协议或者session文件包含来打。实战中,如果站点开了file_put_contents写文件的功能,可以直接写个phar包上去,再通过文件操作函数触发反序列化。
检测ThinkPHP站点,我一般先看响应头里有没有X-Powered-By: ThinkPHP,或者直接访问/index.php?s=index/index/index看报错信息。如果开了debug,报错页面会暴露完整路径和版本号。没开debug的话,可以试/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1,这个payload在5.0.23以下通杀。
修复方案其实官方早就给了。5.0.23之后,Request类的filter属性加了白名单校验,method参数也做了限制。但问题是,很多站长根本不升级。我见过一个站,后台登录页还挂着“ThinkPHP 5.0.10”的版权信息,问运维为什么不升,回答是“怕升级后插件不兼容”。这种心态就是渗透测试的突破口。
最后提一句,ThinkPHP的漏洞利用工具已经非常成熟了,网上能搜到一堆GUI工具,填个URL就能一键getshell。但真正做渗透的时候,别太依赖工具。手动构造payload能帮你理解框架的请求处理流程,遇到WAF拦截的时候,也知道该从哪个参数入手变形绕过。
友情链接