thinkphp多语言模块存在高危rce漏洞,需确认是否启用多语言开关且版本低于安全基线(6.0.13及以下),并检查日志中lang参数的目录穿越试探痕迹。

ThinkPHP 多语言模块的 lang 参数若未经严格校验,会直接拼入文件路径并 include,导致目录穿越 + 任意文件包含(如加载 pearcmd.php),这是高危漏洞,不是“配置不严谨”而是“可直接 RCE”。必须从输入、路径、文件操作三层拦截。
如何确认你的项目是否在危险路径上
检查两点:是否启用了多语言开关,以及当前 ThinkPHP 版本是否低于安全基线。
-
config/lang.php中'switch' => true且未限制'allow_lang_list'—— 已暴露攻击面 - 执行
php -r "echo \think\facade\App::version();",输出为6.0.13或更低 → 确认存在路径校验绕过缺陷 - 线上 Nginx/Apache 日志中搜
lang=\.\/\.或lang=..%2f,有匹配即说明已被扫描或试探
lang 参数必须用白名单正则过滤
不能依赖框架默认行为,lang 必须在请求入口就做硬性截断。中间件是最可靠位置,且需拒绝所有含点、斜杠、控制字符的输入。
- 规则必须只允许标准语言标签格式:
^[a-z]{2}(_[A-Z]{2})?$(如zh-cn、en_US) - 禁止
.、/、\0、%00、..等任何可能参与路径解析的字符 - 长度限制在 5–10 字符内,
zh_CN_XX这类超长值直接 403 - 不要用
stripos($lang, '..')这类黑名单检测 —— 攻击者可用 URL 编码、双写、大小写混用绕过
禁用危险函数比修补路径更有效
即使路径校验漏掉一个字节,只要 include、require、file_get_contents 等函数被禁用,攻击链就断在最后一步。
- 在
php.ini中设置disable_functions = include,require,include_once,require_once,file_get_contents - 注意:禁用后,ThinkPHP 的模板加载、语言包自动发现等功能会报错,需配合白名单路径重写(见下条)
- 生产环境务必删除
/usr/local/lib/php/pearcmd.php等已知危险工具文件,别指望“它不在 web 目录就安全” - 检查
phpinfo()页面,确认register_argc_argv为Off,否则攻击者可通过命令行参数注入
升级不是可选项,是紧急动作
ThinkPHP 官方已在多个版本中修复该问题,但补丁逻辑分散,仅升级不审计配置仍可能残留风险。
- 6.x 用户必须升到
≥ 6.0.14;5.1.x 升到≥ 5.1.9;5.0.x 升到≥ 5.0.13 - 升级后仍要检查
config/lang.php,'switch'默认应为false,'allow_lang_list'不为空 - 如果你用的是自定义语言加载逻辑(比如从数据库读取语言包),
include前必须调用realpath()+str_starts_with()校验是否落在$this->app->getLangPath()下
最常被忽略的一点:攻击者不总走 lang 参数,think-lang 请求头、X-Language、甚至 cookie 中的 lang 字段,只要框架代码里用了 input('lang') 或 $request->header('think-lang'),就都得统一过滤 —— 漏一个入口,整套防御就形同虚设。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











