From 1da50aa61db8257082c97e6e37ffbfcb9b4d13a8 Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Mon, 29 Dec 2014 21:59:23 +0100 Subject: [PATCH] security can now disable special $smarty variables see also NEW_FEATURES.txt --- NEW_FEATURES.txt | 8 + change_log.txt | 4 + ...ernal_compile_private_special_variable.php | 139 +++++++++--------- libs/sysplugins/smarty_security.php | 25 ++++ 4 files changed, 107 insertions(+), 69 deletions(-) diff --git a/NEW_FEATURES.txt b/NEW_FEATURES.txt index 0f34ad99..9118bfc1 100644 --- a/NEW_FEATURES.txt +++ b/NEW_FEATURES.txt @@ -11,3 +11,11 @@ Smarty 3.1.22 - Class names like foo\bar\Baz::FOO, foo\bar\Baz::$foo, foo\bar\Baz::foo() - PHP function names like foo\bar\baz() + Security + ======== + The Smarty_Security class has the new property $disabled_special_smarty_vars. + It's an array which can be loaded with the $smarty special variable names like + 'template_object', 'template', 'current_dir' and others which will be disabled. + Note: That this security checking is performed at compile time. + + \ No newline at end of file diff --git a/change_log.txt b/change_log.txt index f5c8c7ce..47f4166e 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,8 @@ ===== 3.1.22-dev ===== (xx.xx.2014) + 29.12.2014 + - new feature security can now disable special $smarty variables listed in property $disabled_special_smarty_vars + see also NEW_FEATURES.txt (forum 25370) + 27.12.2014 - bugfix clear internal _is_file_cache when plugins_dir was modified diff --git a/libs/sysplugins/smarty_internal_compile_private_special_variable.php b/libs/sysplugins/smarty_internal_compile_private_special_variable.php index 1b6cf375..a4b8d208 100644 --- a/libs/sysplugins/smarty_internal_compile_private_special_variable.php +++ b/libs/sysplugins/smarty_internal_compile_private_special_variable.php @@ -30,88 +30,89 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C $_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2)); $compiled_ref = ' '; $variable = trim($_index[0], "'"); - switch ($variable) { - case 'foreach': - return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; - case 'section': - return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; - case 'capture': - return "Smarty::\$_smarty_vars$parameter"; - case 'now': - return 'time()'; - case 'cookies': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { - $compiler->trigger_template_error("(secure mode) super globals not permitted"); + if (!isset($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedSpecialSmartyVar($variable, $compiler)) { + switch ($variable) { + case 'foreach': + return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; + case 'section': + return "\$_smarty_tpl->getVariable('smarty')->value$parameter"; + case 'capture': + return "Smarty::\$_smarty_vars$parameter"; + case 'now': + return 'time()'; + case 'cookies': + if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { + $compiler->trigger_template_error("(secure mode) super globals not permitted"); + break; + } + $compiled_ref = '$_COOKIE'; break; - } - $compiled_ref = '$_COOKIE'; - break; - case 'get': - case 'post': - case 'env': - case 'server': - case 'session': - case 'request': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { - $compiler->trigger_template_error("(secure mode) super globals not permitted"); + case 'get': + case 'post': + case 'env': + case 'server': + case 'session': + case 'request': + if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) { + $compiler->trigger_template_error("(secure mode) super globals not permitted"); + break; + } + $compiled_ref = '$_' . strtoupper($variable); break; - } - $compiled_ref = '$_' . strtoupper($variable); - break; - case 'template': - return 'basename($_smarty_tpl->source->filepath)'; + case 'template': + return 'basename($_smarty_tpl->source->filepath)'; - case 'template_object': - return '$_smarty_tpl'; + case 'template_object': + return '$_smarty_tpl'; - case 'current_dir': - return 'dirname($_smarty_tpl->source->filepath)'; + case 'current_dir': + return 'dirname($_smarty_tpl->source->filepath)'; - case 'version': - $_version = Smarty::SMARTY_VERSION; + case 'version': + $_version = Smarty::SMARTY_VERSION; - return "'$_version'"; + return "'$_version'"; - case 'const': - if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) { - $compiler->trigger_template_error("(secure mode) constants not permitted"); + case 'const': + if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) { + $compiler->trigger_template_error("(secure mode) constants not permitted"); + break; + } + if (strpos($_index[1], '$') === false) { + return "@constant('{$_index[1]}')"; + } else { + return "@constant({$_index[1]})"; + } + + case 'config': + if (isset($_index[2])) { + return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)"; + } else { + return "\$_smarty_tpl->getConfigVariable($_index[1])"; + } + case 'ldelim': + $_ldelim = $compiler->smarty->left_delimiter; + + return "'$_ldelim'"; + + case 'rdelim': + $_rdelim = $compiler->smarty->right_delimiter; + + return "'$_rdelim'"; + + default: + $compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid'); break; + } + if (isset($_index[1])) { + array_shift($_index); + foreach ($_index as $_ind) { + $compiled_ref = $compiled_ref . "[$_ind]"; } - if( strpos( $_index[1], '$') === false ){ - return "@constant('{$_index[1]}')"; - } else { - return "@constant({$_index[1]})"; - } - - case 'config': - if (isset($_index[2])) { - return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)"; - } else { - return "\$_smarty_tpl->getConfigVariable($_index[1])"; - } - case 'ldelim': - $_ldelim = $compiler->smarty->left_delimiter; - - return "'$_ldelim'"; - - case 'rdelim': - $_rdelim = $compiler->smarty->right_delimiter; - - return "'$_rdelim'"; - - default: - $compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid'); - break; - } - if (isset($_index[1])) { - array_shift($_index); - foreach ($_index as $_ind) { - $compiled_ref = $compiled_ref . "[$_ind]"; } } - return $compiled_ref; } } diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php index 9f7183bd..16a2cd18 100644 --- a/libs/sysplugins/smarty_security.php +++ b/libs/sysplugins/smarty_security.php @@ -115,6 +115,12 @@ class Smarty_Security * @var array */ public $disabled_modifiers = array(); + /** + * This is an array of disabled special $smarty variables. + * + * @var array + */ + public $disabled_special_smarty_vars = array(); /** * This is an array of trusted streams. * If empty all streams are allowed. @@ -273,6 +279,25 @@ class Smarty_Security return false; // should not, but who knows what happens to the compiler in the future? } + /** + * Check if special $smarty variable is trusted. + * + * @param string $var_name + * @param object $compiler compiler object + * + * @return boolean true if tag is trusted + * @throws SmartyCompilerException if modifier is not trusted + */ + public function isTrustedSpecialSmartyVar($var_name, $compiler) + { + if (!in_array($var_name, $this->disabled_special_smarty_vars)) { + return true; + } else { + $compiler->trigger_template_error("special variable '\$smarty.{$var_name}' not allowed by security setting", $compiler->lex->taglineno); + } + + return false; // should not, but who knows what happens to the compiler in the future? + } /** * Check if modifier plugin is trusted.