ThinkPHP本身无RFI漏洞,但开发者误用用户输入拼接路径或开启allow_url_include=On时,结合反序列化等漏洞链可触发RFI/RCE;须禁用allow_url_include、校验动态文件包含参数、加固lang参数路径遍历、关闭调试模式并配置open_basedir等系统防护。

ThinkPHP 本身不直接提供远程文件包含(RFI)的入口,但当开发者误用用户输入拼接文件路径、或开启危险配置(如 allow_url_include=On),配合框架已知漏洞链(如反序列化、lang参数路径遍历),就可能被诱导触发 RFI 或演变为 RCE。真正要防的不是“ThinkPHP有没有RFI漏洞”,而是“你的代码和配置是否给 RFI 留了门”。
确认并禁用 allow_url_include
这是远程文件包含最底层的开关。只要它开着,任何能控制 include()、require() 参数的点都可能被利用。
- 检查 php.ini:搜索
allow_url_include,必须为 Off;若使用宝塔、cPanel 等面板,在 PHP 设置中关闭该选项 - 运行
php -i | grep allow_url_include验证生效状态 - 若项目依赖
file_get_contents('http://...')等功能,改用 cURL 并严格校验响应内容,而非降级开启allow_url_include
堵死所有动态 include 的用户输入源
ThinkPHP 框架层不暴露 include($_GET['file']),但业务代码常自行引入风险:
- 全局搜索项目中所有
include、require、include_once、require_once,重点检查参数含input()、$request->param()、$_GET、$_POST、路由变量(如:id)的位置 - 禁止类似
include APP_PATH . 'plugins/' . input('p') . '.php';的写法;一律改为白名单机制:
if (!in_array($p, ['pay_alipay', 'pay_wx', 'sms_yunpian'])) { throw new HttpException(404); } - 检查自定义模板引擎、插件加载器、钩子行为(hook)中是否拼接文件名,确保其来源经过
basename()+realpath()+ 目录前缀比对三重校验
加固多语言(lang)参数路径遍历风险
该问题在 ThinkPHP 6.0.13 及以下版本中可被用于目录穿越读取任意文件,若服务器存在 pearcmd.php 等可执行脚本,再配合 allow_url_include 就可能达成 RFI/RCE。
- 若无需多语言,直接在
config/lang.php中设'switch' => false,并从app/middleware.php移除\think\middleware\LoadLangPack::class - 若必须启用,请在语言包加载前强制校验:
$base = realpath(config('lang.path'));
$target = realpath($base . DIRECTORY_SEPARATOR . $request->param('lang', 'zh-cn') . '.php');
if (!$target || strpos($target, $base) !== 0) { throw new HttpException(400); } - 生产环境务必关闭
app_debug => false和show_error_msg => false,防止错误信息泄露真实路径
辅助系统层防护(非替代代码修复)
代码加固是根本,系统配置是兜底。二者缺一不可:
- 在 php.ini 中设置
open_basedir,限制脚本仅能访问项目根目录及必要子目录(如runtime/、public/) - Nginx 场景下,添加规则拦截可疑请求:
if ($args ~* "(base64|unserialize|O:|s:|a:).*lang=") { return 403; } - 删除或权限收紧服务器上的高危文件,例如:
chmod 000 /usr/local/lib/php/pearcmd.php - 禁用 PHP 危险配置:
register_argc_argv = Off,disable_functions = exec,passthru,shell_exec,system,proc_open,popen(按需)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











