diff --git a/CHANGELOG.md b/CHANGELOG.md index ac306dce..4db26f2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Security +- Prevent evasion of the `static_classes` security policy. This addresses CVE-2021-21408 + ## [3.1.42] - 2022-01-10 ### Security diff --git a/lexer/smarty_internal_templateparser.y b/lexer/smarty_internal_templateparser.y index c6890642..8f812021 100644 --- a/lexer/smarty_internal_templateparser.y +++ b/lexer/smarty_internal_templateparser.y @@ -758,6 +758,9 @@ value(res) ::= doublequoted_with_quotes(s). { value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). { + if ($this->security && $this->security->static_classes !== array()) { + $this->compiler->trigger_template_error('dynamic static class not allowed by security setting'); + } $prefixVar = $this->compiler->getNewPrefixVariable(); if (vi['var'] === '\'smarty\'') { $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>'); diff --git a/libs/sysplugins/smarty_internal_templateparser.php b/libs/sysplugins/smarty_internal_templateparser.php index aaeae63b..7c8735cf 100644 --- a/libs/sysplugins/smarty_internal_templateparser.php +++ b/libs/sysplugins/smarty_internal_templateparser.php @@ -2837,6 +2837,10 @@ class Smarty_Internal_Templateparser // line 765 "../smarty/lexer/smarty_internal_templateparser.y" public function yy_r95() { + if ($this->security && $this->security->static_classes !== array()) { + $this->compiler->trigger_template_error('dynamic static class not allowed by security setting'); + } + $prefixVar = $this->compiler->getNewPrefixVariable(); if ($this->yystack[ $this->yyidx + -2 ]->minor[ 'var' ] === '\'smarty\'') { $this->compiler->appendPrefixCode("assertEquals('25', $this->smarty->fetch($tpl)); } -/** - * test not trusted PHP function - * @expectedException SmartyException - * @expectedExceptionMessage access to static class 'mysecuritystaticclass' not allowed by security setting - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testNotTrustedStaticClass() - { - $this->smarty->security_policy->static_classes = array('null'); - $this->smarty->fetch('string:{mysecuritystaticclass::square(5)}'); - } + /** + * test not trusted PHP function + * @expectedException SmartyException + * @expectedExceptionMessage access to static class 'mysecuritystaticclass' not allowed by security setting + */ + public function testNotTrustedStaticClass() + { + $this->smarty->security_policy->static_classes = array('null'); + $this->smarty->fetch('string:{mysecuritystaticclass::square(5)}'); + } + + /** + * test not trusted PHP function + * @expectedException SmartyException + * @expectedExceptionMessage dynamic static class not allowed by security setting + */ + public function testNotTrustedStaticClassEval() + { + $this->smarty->security_policy->static_classes = array('null'); + $this->smarty->fetch('string:{$test = "mysecuritystaticclass"}{$test::square(5)}'); + } + + /** + * test not trusted PHP function + * @expectedException SmartyException + * @expectedExceptionMessage dynamic static class not allowed by security setting + */ + public function testNotTrustedStaticClassSmartyVar() + { + $this->smarty->security_policy->static_classes = array('null'); + $this->smarty->fetch('string:{$smarty.template_object::square(5)}'); + } public function testChangedTrustedDirectory() {