ThinkPHP多语言漏洞核心风险是lang参数未经校验直接拼接路径,导致目录遍历和任意文件包含;最可靠修复方式是关闭lang_switch_on配置并移除LoadLangPack中间件。

ThinkPHP多语言漏洞的核心风险来自 lang 参数未经校验直接拼接路径,导致目录遍历和任意文件包含(如读取 /etc/passwd 或触发 pearcmd.php RCE)。关闭 lang_switch_on(或对应配置项)是**最直接、最可靠的修复方式**,尤其适用于实际无需多语言的国内项目。
确认是否真启用了多语言功能
不是所有 ThinkPHP 6 项目都受影响,只有明确启用才需处理:
- 检查
app/middleware.php是否注册了\think\middleware\LoadLangPack::class - 查看
config/lang.php中'switch' => true(6.x)或'lang_switch_on' => true(5.x) - 全局搜索代码中是否存在
Lang::setLangSet()、$app->lang->setLangSet()或手动解析input('lang')的逻辑
彻底关闭 lang 切换功能
关闭后,框架将忽略所有 lang=xxx 请求参数,从源头杜绝攻击面:
- 在
config/lang.php中强制设为:'switch' => false(6.x)或'lang_switch_on' => false(5.x) - 从
app/middleware.php中移除或注释掉\think\middleware\LoadLangPack::class - 删除或重命名
app/lang/目录(避免被其他入口试探读取) - 检查前端模板、JS 或接口文档,清理残留的
?lang=链接或请求,防止误触发扫描或测试工具告警
升级后仍需验证配置是否生效
即使已升级到 6.0.14+,若配置未清理,旧逻辑仍可能被绕过:
立即学习“PHP免费学习笔记(深入)”;
- 访问任意接口并附加
?lang=../../etc/passwd,确认返回 400 或默认页面,而非报错信息或文件内容 - 用
php think version确认运行版本确为 6.0.14 或更高 - 确保生产环境
app_debug = false,禁用错误详情输出
不升级时的手动加固要点
若因兼容性无法升级,必须在自定义语言加载处补上路径校验:
- 获取
$lang后立即调用basename($lang)提取基础标识(防zh-cn/..类构造) - 拼出完整路径后,用
realpath()解析真实路径 - 严格比对该路径是否以合法语言目录开头:
strpos(realpath($target), realpath(config('lang.path'))) === 0 - 任一校验失败,必须抛出
HttpException(400),禁止静默降级或继续执行



















