ThinkPHP 6.0.12 lang参数漏洞本质是未路径规范化与白名单校验,导致任意文件读取甚至RCE;修复需升级至6.0.14+或手动添加realpath+白名单校验,并禁用register_argc_argv等危险配置。

ThinkPHP 6.0.12 的 lang 参数文件包含漏洞本质是未对用户输入做路径规范化与白名单校验,导致攻击者可通过 lang=../../etc/passwd 或 lang=../../usr/local/lib/php/pearcmd.php 实现任意文件读取甚至远程代码执行(RCE)。该漏洞已在 6.0.14 版本修复,但若因兼容性无法升级,需手动加固。
确认是否启用多语言功能
不是所有项目都受影响,只有启用多语言中间件时才存在风险:
- 检查
app/middleware.php是否注册了\think\middleware\LoadLangPack::class - 查看
config/lang.php中'switch' => true是否开启语言切换 - 搜索项目中是否有
Lang::setLangSet()或$app->lang->setLangSet()调用 - 即使未主动配置,某些第三方插件(如 FastAdmin、ThinkAdmin)可能默认启用
升级到安全版本(推荐首选)
官方已在 6.0.14 及后续 LTS 版本中重构 LoadLangPack 行为,禁用动态路径拼接,并引入强制路径校验:
- 升级命令:
composer update topthink/framework:^6.0.14 - 升级后仍需检查
config/lang.php中的path配置是否指向合法目录(如app/lang/) - 确认生产环境已关闭
app_debug = false和show_error_msg = false
手动修复 lang 参数校验逻辑
若无法升级,必须在加载语言包前插入严格路径校验。不能仅用 basename() 或简单过滤,必须结合 realpath() 与白名单比对:
立即学习“PHP免费学习笔记(深入)”;
- 获取原始 lang 值:
$lang = $request->param('lang', 'zh-cn'); - 构造目标路径并解析真实路径:
$baseDir = realpath(config('lang.path', app()->getAppPath() . 'lang'));$target = realpath($baseDir . DIRECTORY_SEPARATOR . $lang . '.php'); - 校验是否落在合法目录内:
if (!$target || strpos($target, $baseDir) !== 0) { throw new HttpException(400, 'Invalid lang'); } - 禁止直接拼接
$lang到include或file_get_contents中
禁用危险 PHP 配置(辅助加固)
即使修复了路径校验,若服务器启用了 register_argc_argv=On 且安装了 PEAR,仍可能通过 pearcmd.php 触发 RCE:
- 在
php.ini中设置:register_argc_argv = Off - 删除或权限限制
/usr/local/lib/php/pearcmd.php(如chmod 000) - 生产环境禁用
allow_url_include = Off和disable_functions = include, require, file_get_contents(按需) - 确保 Web 服务器(Nginx/Apache)不将
.php文件以静态资源方式返回源码



















