Skip to content

Commit

Permalink
Update AMS smarty to 3.1.47 and merge with our changes
Browse files Browse the repository at this point in the history
  • Loading branch information
kaetemi committed Feb 21, 2023
1 parent 62d3e50 commit 628f8cd
Show file tree
Hide file tree
Showing 18 changed files with 244 additions and 73 deletions.
59 changes: 57 additions & 2 deletions web/private_php/ams/smarty/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Output buffer is now cleaned for internal PHP errors as well, not just for Exceptions [#514](https://github.com/smarty-php/smarty/issues/514)

## [3.1.47] - 2022-09-14

### Security
- Applied appropriate javascript and html escaping in mailto plugin to counter injection attacks [#454](https://github.com/smarty-php/smarty/issues/454)

### Fixed
- Fixed use of `rand()` without a parameter in math function [#794](https://github.com/smarty-php/smarty/issues/794)
- Fixed unselected year/month/day not working in html_select_date [#395](https://github.com/smarty-php/smarty/issues/395)
- Updated requirement contraint for 'php' in composer.json to correctly reflect that Smarty3 does not support PHP8. Please upgrade to Smarty4 to use PHP8.

## [3.1.46] - 2022-08-01

### Fixed
- Fixed problems with smarty_mb_str_replace [#549](https://github.com/smarty-php/smarty/issues/549)
- Fixed second parameter of unescape modifier not working [#777](https://github.com/smarty-php/smarty/issues/777)

## [3.1.45] - 2022-05-17

### Security
- Prevent PHP injection through malicious block name or include file name. This addresses CVE-2022-29221

### Fixed
- Math equation `max(x, y)` didn't work anymore [#721](https://github.com/smarty-php/smarty/issues/721)

## [3.1.44] - 2022-01-18

### Fixed
- Fixed illegal characters bug in math function security check [#702](https://github.com/smarty-php/smarty/issues/702)

## [3.1.43] - 2022-01-10

### Security
- Prevent evasion of the `static_classes` security policy. This addresses CVE-2021-21408

## [3.1.42] - 2022-01-10

### Security
- Prevent arbitrary PHP code execution through maliciously crafted expression for the math function. This addresses CVE-2021-29454

## [3.1.41] - 2022-01-09

### Security
- Rewrote the mailto function to not use `eval` when encoding with javascript

## [3.1.40] - 2021-10-13

### Changed
- modifier escape now triggers a E_USER_NOTICE when an unsupported escape type is used https://github.com/smarty-php/smarty/pull/649

### Security
- More advanced javascript escaping to handle https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements thanks to m-haritonov

## [3.1.39] - 2021-02-17

### Security
- Prevent access to `$smarty.template_object` in sandbox mode
- Fixed code injection vulnerability by using illegal function names in `{function name='blah'}{/function}`
- Prevent access to `$smarty.template_object` in sandbox mode. This addresses CVE-2021-26119.
- Fixed code injection vulnerability by using illegal function names in `{function name='blah'}{/function}`. This addresses CVE-2021-26120.

## [3.1.38] - 2021-01-08

Expand Down
2 changes: 1 addition & 1 deletion web/private_php/ams/smarty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Smarty can be run with PHP 5.2 to PHP 7.4.
> Read the NEW_FEATURES and INHERITANCE_RELEASE_NOTES file for recent extensions to Smarty 3.1 functionality
Smarty versions 3.1.11 or later are now on github and can be installed with Composer.
Smarty versions 3.1.11 or later are now on GitHub and can be installed with Composer.


The "smarty/smarty" package will start at libs/.... subfolder.
Expand Down
2 changes: 1 addition & 1 deletion web/private_php/ams/smarty/libs/Smarty.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.39';
const SMARTY_VERSION = '3.1.47';
/**
* define variable scopes
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
$field_separator = "\n";
$option_separator = "\n";
$time = null;

// $all_empty = null;
// $day_empty = null;
// $month_empty = null;
Expand All @@ -113,17 +114,7 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
foreach ($params as $_key => $_value) {
switch ($_key) {
case 'time':
if (!is_array($_value) && $_value !== null) {
$template->_checkPlugins(
array(
array(
'function' => 'smarty_make_timestamp',
'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'
)
)
);
$time = smarty_make_timestamp($_value);
}
$$_key = $_value; // we'll handle conversion below
break;
case 'month_names':
if (is_array($_value) && count($_value) === 12) {
Expand Down Expand Up @@ -178,43 +169,59 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
}
// Note: date() is faster than strftime()
// Note: explode(date()) is faster than date() date() date()
if (isset($params[ 'time' ]) && is_array($params[ 'time' ])) {
if (isset($params[ 'time' ][ $prefix . 'Year' ])) {

if (isset($time) && is_array($time)) {
if (isset($time[$prefix . 'Year'])) {
// $_REQUEST[$field_array] given
foreach (array(
'Y' => 'Year',
'm' => 'Month',
'd' => 'Day'
) as $_elementKey => $_elementName) {
'Y' => 'Year',
'm' => 'Month',
'd' => 'Day'
) as $_elementKey => $_elementName) {
$_variableName = '_' . strtolower($_elementName);
$$_variableName =
isset($params[ 'time' ][ $prefix . $_elementName ]) ? $params[ 'time' ][ $prefix . $_elementName ] :
isset($time[$prefix . $_elementName]) ? $time[$prefix . $_elementName] :
date($_elementKey);
}
} elseif (isset($params[ 'time' ][ $field_array ][ $prefix . 'Year' ])) {
} elseif (isset($time[$field_array][$prefix . 'Year'])) {
// $_REQUEST given
foreach (array(
'Y' => 'Year',
'm' => 'Month',
'd' => 'Day'
) as $_elementKey => $_elementName) {
'Y' => 'Year',
'm' => 'Month',
'd' => 'Day'
) as $_elementKey => $_elementName) {
$_variableName = '_' . strtolower($_elementName);
$$_variableName = isset($params[ 'time' ][ $field_array ][ $prefix . $_elementName ]) ?
$params[ 'time' ][ $field_array ][ $prefix . $_elementName ] : date($_elementKey);
$$_variableName = isset($time[$field_array][$prefix . $_elementName]) ?
$time[$field_array][$prefix . $_elementName] : date($_elementKey);
}
} else {
// no date found, use NOW
list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
list($_year, $_month, $_day) = explode('-', date('Y-m-d'));
}
} elseif (isset($time) && preg_match("/(\d*)-(\d*)-(\d*)/", $time, $matches)) {
$_year = $_month = $_day = null;
if ($matches[1] > '') $_year = (int) $matches[1];
if ($matches[2] > '') $_month = (int) $matches[2];
if ($matches[3] > '') $_day = (int) $matches[3];
} elseif ($time === null) {
if (array_key_exists('time', $params)) {
$_year = $_month = $_day = $time = null;
$_year = $_month = $_day = null;
} else {
list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
list($_year, $_month, $_day) = explode('-', date('Y-m-d'));
}
} else {
list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d', $time));
$template->_checkPlugins(
array(
array(
'function' => 'smarty_make_timestamp',
'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'
)
)
);
$time = smarty_make_timestamp($time);
list($_year, $_month, $_day) = explode('-', date('Y-m-d', $time));
}

// make syntax "+N" or "-N" work with $start_year and $end_year
// Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr
foreach (array(
Expand Down
38 changes: 24 additions & 14 deletions web/private_php/ams/smarty/libs/plugins/function.mailto.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,33 @@
*/
function smarty_function_mailto($params)
{
static $_allowed_encoding =
array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true);
static $_allowed_encoding = array(
'javascript' => true,
'javascript_charcode' => true,
'hex' => true,
'none' => true
);

$extra = '';
if (empty($params[ 'address' ])) {
trigger_error("mailto: missing 'address' parameter", E_USER_WARNING);
return;
} else {
$address = $params[ 'address' ];
}

$text = $address;

// netscape and mozilla do not decode %40 (@) in BCC field (bug?)
// so, don't encode it.
$search = array('%40', '%2C');
$replace = array('@', ',');
$mail_parms = array();
foreach ($params as $var => $value) {
switch ($var) {
case 'cc':
case 'bcc':
case 'followupto':
if (!empty($value)) {
$mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value));
$mail_parms[] = $var . '=' . str_replace(array('%40', '%2C'), array('@', ','), rawurlencode($value));
}
break;
case 'subject':
Expand All @@ -83,6 +88,7 @@ function smarty_function_mailto($params)
default:
}
}

if ($mail_parms) {
$address .= '?' . join('&', $mail_parms);
}
Expand All @@ -94,22 +100,26 @@ function smarty_function_mailto($params)
);
return;
}
// FIXME: (rodneyrehm) document.write() excues me what? 1998 has passed!

$flags = ENT_QUOTES;
if (defined('ENT_SUBSTITUTE') && defined('ENT_HTML401')) {
$flags |= ENT_SUBSTITUTE | ENT_HTML401;
}

$string = '<a href="mailto:' . htmlspecialchars($address, $flags, Smarty::$_CHARSET) .
'" ' . $extra . '>' . htmlspecialchars($text, $flags, Smarty::$_CHARSET) . '</a>';

if ($encode === 'javascript') {
$string = 'document.write(\'<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>\');';
$js_encode = '';
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
$js_encode .= '%' . bin2hex($string[ $x ]);
}
return '<script type="text/javascript">eval(unescape(\'' . $js_encode . '\'))</script>';
return '<script type="text/javascript">document.write(unescape(\'' . $js_encode . '\'))</script>';
} elseif ($encode === 'javascript_charcode') {
$string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
for ($x = 0, $y = strlen($string); $x < $y; $x++) {
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
$ord[] = ord($string[ $x ]);
}
$_ret = "<script type=\"text/javascript\" language=\"javascript\">\n" . "{document.write(String.fromCharCode(" .
implode(',', $ord) . "))" . "}\n" . "</script>\n";
return $_ret;
return '<script type="text/javascript">document.write(String.fromCharCode(' . implode(',', $ord) . '))</script>';
} elseif ($encode === 'hex') {
preg_match('!^(.*)(\?.*)$!', $address, $match);
if (!empty($match[ 2 ])) {
Expand All @@ -132,6 +142,6 @@ function smarty_function_mailto($params)
return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
} else {
// no encoding
return '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
return $string;
}
}
32 changes: 31 additions & 1 deletion web/private_php/ams/smarty/libs/plugins/function.math.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ function smarty_function_math($params, $template)
'int' => true,
'abs' => true,
'ceil' => true,
'acos' => true,
'acosh' => true,
'cos' => true,
'cosh' => true,
'deg2rad' => true,
'rad2deg' => true,
'exp' => true,
'floor' => true,
'log' => true,
Expand All @@ -39,27 +44,51 @@ function smarty_function_math($params, $template)
'pow' => true,
'rand' => true,
'round' => true,
'asin' => true,
'asinh' => true,
'sin' => true,
'sinh' => true,
'sqrt' => true,
'srand' => true,
'tan' => true
'atan' => true,
'atanh' => true,
'tan' => true,
'tanh' => true
);

// be sure equation parameter is present
if (empty($params[ 'equation' ])) {
trigger_error("math: missing equation parameter", E_USER_WARNING);
return;
}
$equation = $params[ 'equation' ];

// 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.'(?1))?)+$/';

if (!preg_match($regexp, $equation)) {
trigger_error("math: illegal characters", E_USER_WARNING);
return;
}

// make sure parenthesis are balanced
if (substr_count($equation, '(') !== substr_count($equation, ')')) {
trigger_error("math: unbalanced parenthesis", E_USER_WARNING);
return;
}

// disallow backticks
if (strpos($equation, '`') !== false) {
trigger_error("math: backtick character not allowed in equation", E_USER_WARNING);
return;
}

// also disallow dollar signs
if (strpos($equation, '$') !== false) {
trigger_error("math: dollar signs not allowed in equation", E_USER_WARNING);
Expand Down Expand Up @@ -96,6 +125,7 @@ function smarty_function_math($params, $template)
}
$smarty_math_result = null;
eval("\$smarty_math_result = " . $equation . ";");

if (empty($params[ 'format' ])) {
if (empty($params[ 'assign' ])) {
return $smarty_math_result;
Expand Down
7 changes: 6 additions & 1 deletion web/private_php/ams/smarty/libs/plugins/modifier.escape.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
'"' => '\\"',
"\r" => '\\r',
"\n" => '\\n',
'</' => '<\/'
'</' => '<\/',
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
'<!--' => '<\!--',
'<s' => '<\s',
'<S' => '<\S'
)
);
case 'mail':
Expand Down Expand Up @@ -250,6 +254,7 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
}
return $return;
default:
trigger_error("escape: unsupported type: $esc_type - returning unmodified string", E_USER_NOTICE);
return $string;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'",' . $params[ 0 ] . ')';
case 'javascript':
// escape quotes and backslashes, newlines, etc.
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
return 'strtr(' .
$params[ 0 ] .
', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/" ))';
', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/", "<!--" => "<\!--", "<s" => "<\s", "<S" => "<\S" ))';
}
} catch (SmartyException $e) {
// pass through to regular plugin fallback
Expand Down
Loading

0 comments on commit 628f8cd

Please sign in to comment.