ThinkPHP 6.0.13 的 lang 参数文件包含漏洞本质是未校验路径,导致任意文件读取或RCE;已在6.0.14修复,需升级或手动校验realpath与白名单前缀。

ThinkPHP 6.0.13 的 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()或input('lang')后拼接路径的自定义逻辑 - 注意第三方插件(如 FastAdmin、ThinkAdmin)可能默认启用该中间件,即使你没手动配置
优先升级到 6.0.14 或更高版本
官方已在 6.0.14 中重构 LoadLangPack 行为,禁用动态路径拼接,并强制路径校验:
- 执行升级命令:
composer update topthink/framework:^6.0.14 - 升级后检查
config/lang.php的path配置是否指向合法目录(如app/lang/) - 确保生产环境已关闭
app_debug = false和show_error_msg = false
无法升级时必须手动加路径校验
不能只用 basename() 或简单字符串过滤,必须结合 realpath() 与白名单比对:
立即学习“PHP免费学习笔记(深入)”;
- 获取原始 lang 值:
$lang = $request->param('lang', 'zh-cn'); - 构造并解析真实路径:
$baseDir = realpath(config('lang.path', app()->getAppPath() . 'lang'));$target = realpath($baseDir . DIRECTORY_SEPARATOR . basename($lang) . '.php'); - 严格校验路径前缀:
if (!$target || strpos($target, $baseDir) !== 0) { throw new HttpException(400, 'Invalid lang'); } - 禁止将
$lang直接用于include、require或file_get_contents
禁用危险 PHP 配置并关闭非必要功能
辅助加固可大幅降低 RCE 风险:
- 在
php.ini中设置:register_argc_argv = Off - 设
allow_url_include = Off,并按需加入disable_functions = include, require, file_get_contents - 删除或限制权限:
/usr/local/lib/php/pearcmd.php(如chmod 000) - 若项目无需动态语言切换,直接在
config/lang.php设'switch' => false,并从中间件中移除LoadLangPack



















