概述
smarty 模板的使用比较简单,主要有两个核心函数。一个是 assign()
,把模板中要使用的数据进行欲赋值,一个是 display()
,用来解析和展示最后的视图模板。
CVE 描述信息:
Smarty 3 before 3.1.32 is vulnerable to a PHP code injection when calling fetch() or display() functions on custom resources that does not sanitize template name.
信息的源头,更新日志:https://github.com/smarty-php/smarty/blob/master/change_log.txt
21.7.2017 - security possible PHP code injection on custom resources at display() or fetch() calls if the resource does not sanitize the template name
影响版本
smarty <= 3.1.21
环境搭建
可以把项目 clone 下来,再切到 v3.1.31 。我这里是用 composer 创的。
git checkout tags/v3.1.31 -b v3.1.21-debug
Insomni’hack teaser 2018 拿这个点出了个题 Smart-Y ,这有 wp https://ctftime.org/writeup/8552。
<?php require 'vendor/autoload.php' ;class news extends Smarty_Resource_Custom { protected function fetch ($name, &$source, &$mtime) { $template = "CVE-2017-1000480 smarty PHP code injection" ; $source = $template; $mtime = time(); } } $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->modifiers = array (); $smarty->enableSecurity($my_security_policy); $smarty->setCacheDir('cache' ); $smarty->setCompileDir('compile' ); $smarty->registerResource('news' , new news); $smarty->display('news:' . $_GET['j' ]);
复现
注释符还可以用 */phpinfo();/*
,但 Windows 下文件名不能含有 \/:*?"<>|
,所以 //
更通用。
分析
先看下官方给的补丁。
https://github.com/smarty-php/smarty/commit/614ad1f8b9b00086efc123e49b7bb8efbfa81b61
PoC 生成的临时文件如下。如果没有 PoC,那就随便输一点内容测试一下。
<?php phpinfo(); 'has_nocache_code' => false , 'file_dependency' => array ( '1f7fa551e77a29c48c7ac4143a2b811ca7e38ce5' => array ( 0 => 'news:*/phpinfo();//' , 1 => 1580539358 , 2 => 'news' , ), ), ?> CVE-2017 -1000480 smarty PHP code injection<?php } }
结合上面的内容来看,模板显然是从这里产生的。
$output = "<?php\n" ; $output .= "/* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S" ) . "\n from \"" . $_template->source->filepath . "\" */\n\n" ; $output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n" ;
$_template->source->filepath 这个变量的内容一旦把前面的注释符闭合,就能插入 PHP 代码。
所以官方打的补丁也是针对这些输出点进行过滤。
总结
文档地址:https://www.smarty.net/docs/zh_CN/
暂时没想到利用场景,后期有缘遇到再继续深入吧。
参考
https://chybeta.github.io/2018/01/23/CVE-2017-1000480-Smarty-3-1-32-php%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C-%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
评论