thinkphp 5.0.12存在文件包含漏洞(cve-2018-10020),因模板渲染中未过滤用户输入,导致extract()覆盖$cachefile等变量,触发任意文件包含;需重点审计assign+fetch组合、动态模板路径及日志/上传点是否可利用。

ThinkPHP 5.0.12 存在明确的文件包含漏洞(CVE-2018-10020 等相关变种),核心风险点集中在模板渲染流程中对用户输入的变量未做严格过滤,导致 extract() 覆盖关键路径变量(如 $cacheFile),最终触发任意文件包含。审计时需聚焦「可控输入 → 变量赋值 → 模板加载 → extract → include」这一调用链。
重点关注 assign + fetch 组合的控制器逻辑
该版本下最典型的高危模式是:直接将 request 参数(尤其是 GET/POST)不经清洗就传给 assign(),再调用 fetch() 渲染模板。例如:
$this->assign(request()->get()); return $this->fetch();$this->assign(input('get.')); return $this->fetch('index');
只要控制器中出现这类写法,且模板路径未硬编码(如 fetch() 不带参数或参数可控),就具备文件包含前提条件。需逐个检查 application/*/controller/ 下所有控制器方法。
追踪 fetch() 到 Template::read() 的路径
从 fetch() 入手,顺藤摸瓜跟进以下关键位置:
-
think\View::fetch()→ 路由到具体视图驱动(通常是think\view\driver\Think) - 进入
think\Template::fetch()→ 调用read($cacheFile) - 最终抵达
think\template\driver\File::read(),此处存在extract($vars, EXTR_OVERWRITE)
重点确认 $vars 是否来自用户输入(如 assign 过来的数组),以及 $cacheFile 是否在 extract 后被覆盖——若攻击者能传入 cacheFile=../runtime/log/xxx.php,即可控制包含路径。
检查是否存在危险的动态模板名
除变量覆盖外,还需排查 fetch() 的第一个参数是否可控。常见风险写法包括:
return $this->fetch(input('template'));return $this->fetch(request()->param('t'));$tpl = $_GET['f']; $this->fetch($tpl);
只要模板路径字符串拼接或直接使用用户输入,且未限制前缀、白名单校验或禁止目录跳转(如 ../),就可能绕过默认视图目录限制,造成任意文件读取或包含。
验证 allow_url_include 和文件可访问性
文件包含本身不等于 RCE,但若满足以下任一条件,风险升级为远程代码执行:
- PHP 配置中
allow_url_include = On,可构造php://filter或远程 URL 包含 - 目标存在可写日志文件(如
runtime/log/202610/15.log),且内容可控(如错误信息、调试输出含 PHP 标签) - 上传功能允许保存带 PHP 代码的图片/文本文件(如
test.jpg),且后缀未被严格拦截
建议结合本地复现环境,用 cacheFile=../runtime/log/202610/15.log 或 template=../public/shell.php 实测是否成功包含并解析 PHP 代码。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











