漏洞报告
Smarty 是 PHP 的模板引擎,有助于将表示 (HTML/CSS) 与应用程序逻辑分离。在 3.1.42 和 4.0.2 版本之前,模板作者可以通过制作恶意数学字符串来运行任意 PHP 代码。如果数学字符串作为用户提供的数据传递给数学函数,则外部用户可以通过制作恶意数学字符串来运行任意 PHP 代码。用户应升级到版本 3.1.42 或 4.0.2 以接收补丁。
源码分析
对比官方修复的代码,在/plugins/function.math.php添加了如下一段
// Remove whitespaces
$equation = preg_replace('/\s+/', '', $equation);
// Adapted from https://www.php.net/manual/en/function.eval.php#107377
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';
$operators = '[+/*^%-]'; // Allowed math operators
$regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*((?1)+)|((?1)+)))(?:'.$operators.'(?2))?)+$/';
if (!preg_match($regexp, $equation)) {
trigger_error("math: illegal characters", E_USER_WARNING);
return;
}
对恶意拼接的数学字符串进行过滤(漏洞利用POC格式其实也在这里写出来了,参考$regexp)
而在较低版本下,缺少过滤部分,进而导致RCE
具体的POC我会在下面利用部分详写的
并且,在tests/UnitTests/TemplateSource/ValueTests/Math/MathTest.php中,也有添加
/**
* @expectedException PHPUnit_Framework_Error_Warning
*/
public function testBackticksIllegal()
{
$expected = "22.00";
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="`ls` x * y" x=$x y=$y}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
/**
* @expectedException PHPUnit_Framework_Error_Warning
*/
public function testDollarSignsIllegal()
{
$expected = "22.00";
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="$" x=$x y=$y}');
$this->assertEquals($expected, $this->smarty->fetch($tpl));
}
/**
* &#