ThinkPHP文件包含漏洞源于用户输入直接参与文件路径拼接且未校验,关键在lang参数和模板变量覆盖导致LFI;防御需关闭动态语言切换、白名单校验、realpath路径约束及升级安全版本。

ThinkPHP文件包含漏洞不是框架“不能用”,而是加载逻辑被绕过后的结果。核心问题从来不在多语言或模板功能本身,而在于用户输入是否直接参与了文件路径拼接,且未经过路径净化、白名单校验与真实路径约束。
关键漏洞点:lang参数与模板变量覆盖
多语言模块的Lang::load()在6.0.13及更早版本中,会将$_GET['lang']未经处理就拼入语言包路径,导致目录穿越(如?lang=../../../../etc/passwd);ThinkPHP5模板引擎中的fetch()配合assign()和extract(),若接收用户参数后未过滤,可能覆盖内部变量、触发恶意cacheFile路径加载——这两类都是典型“可控路径+未校验”导致的本地文件包含(LFI)。
真正有效的防御手段
防御不是加一层WAF或改个配置,而是从加载源头切断攻击链:
- 关闭动态语言切换:将config/lang.php中'switch' => false,彻底禁用运行时lang参数解析
- 必须支持切换时,只允许预设值:配置'allow_lang_list' => ['zh-cn', 'en-us'],并在中间件中严格校验$this->request->param('lang')是否在此列表
- 路径强制标准化:重写或拦截Lang::load()逻辑,在打开文件前调用realpath($file),再用str_starts_with()确认其落在config('lang.path')真实路径之下
- 模板层禁用危险组合:避免在控制器中直接$this->assign($_GET);如需动态传参,应显式声明白名单键名,而非全量覆盖
配套加固不可少
单点修复容易被绕过,需结合环境与框架层协同防护:
立即学习“PHP免费学习笔记(深入)”;
- 升级到安全版本:ThinkPHP 6.0.14 / 5.1.9 / 5.0.13 及以上已修复对应LFI路径处理逻辑
- 禁用危险PHP配置:确保allow_url_include = Off,并检查open_basedir是否合理限制可访问路径范围
- 日志与缓存目录权限隔离:将Runtime/、lang/等敏感目录移出Web根目录,或通过Web服务器配置禁止直接HTTP访问
- Cookie默认启用HttpOnly:在config/cookie.php中设置'httponly' => true,缓解XSS辅助利用风险
漏洞本质是信任边界错位。ThinkPHP提供了灵活的加载机制,但开发者必须明确:任何来自客户端的输入,都不能直接成为include、require、file_get_contents等函数的路径参数。守住这个边界,比研究绕过技巧重要得多。



















