security can now disable special $smarty variables

see also NEW_FEATURES.txt
This commit is contained in:
Uwe Tews
2014-12-29 21:59:23 +01:00
parent 49a3427515
commit 1da50aa61d
4 changed files with 107 additions and 69 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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.