mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-04 02:14:26 +02:00
- bugfix possible Security Vulnerability in Smarty_Security class.
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
===== 3.1.32 - dev ===
|
===== 3.1.32 - dev ===
|
||||||
|
24.04.2018
|
||||||
|
- bugfix possible Security Vulnerability in Smarty_Security class.
|
||||||
|
|
||||||
26.03.2018
|
26.03.2018
|
||||||
- bugfix plugins may not be loaded if {function} or {block} tags are executed in nocache mode
|
- bugfix plugins may not be loaded if {function} or {block} tags are executed in nocache mode
|
||||||
https://github.com/smarty-php/smarty/issues/371
|
https://github.com/smarty-php/smarty/issues/371
|
||||||
|
@@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
/**
|
/**
|
||||||
* smarty version
|
* smarty version
|
||||||
*/
|
*/
|
||||||
const SMARTY_VERSION = '3.1.32-dev-45';
|
const SMARTY_VERSION = '3.1.32-dev-46';
|
||||||
/**
|
/**
|
||||||
* define variable scopes
|
* define variable scopes
|
||||||
*/
|
*/
|
||||||
@@ -1042,9 +1042,15 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
*/
|
*/
|
||||||
public function _realpath($path, $realpath = null)
|
public function _realpath($path, $realpath = null)
|
||||||
{
|
{
|
||||||
$nds = DIRECTORY_SEPARATOR === '/' ? '\\' : '/';
|
static $nds = array('/' => '\\', '\\' => '/');
|
||||||
|
static $sepDotsep = DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR;
|
||||||
|
static $sepDot = DIRECTORY_SEPARATOR . '.';
|
||||||
|
static $sepSep = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
|
||||||
// normalize DIRECTORY_SEPARATOR
|
// normalize DIRECTORY_SEPARATOR
|
||||||
$path = str_replace($nds, DIRECTORY_SEPARATOR, $path);
|
$path = str_replace(array($nds[DIRECTORY_SEPARATOR], $sepDotsep), DIRECTORY_SEPARATOR, $path);
|
||||||
|
if (strpos($path,$sepDot) === false && (($realpath === false && $path[0] === '.') || $realpath === null) && $path[0] !== '\\') {
|
||||||
|
return $path;
|
||||||
|
}
|
||||||
preg_match('%^(?<root>(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
|
preg_match('%^(?<root>(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
|
||||||
$path,
|
$path,
|
||||||
$parts);
|
$parts);
|
||||||
@@ -1056,11 +1062,11 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
$path = getcwd() . DIRECTORY_SEPARATOR . $path;
|
$path = getcwd() . DIRECTORY_SEPARATOR . $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns
|
// remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns
|
||||||
$path = preg_replace('#([\\\\/]([.]?[\\\\/])+)#u', DIRECTORY_SEPARATOR, $path);
|
$path = str_replace(array($sepDotsep,$sepSep), DIRECTORY_SEPARATOR, $path);
|
||||||
// resolve '..DIRECTORY_SEPARATOR' pattern, smallest first
|
// resolve '..DIRECTORY_SEPARATOR' pattern, smallest first
|
||||||
if (strpos($path, '..' . DIRECTORY_SEPARATOR) !== false &&
|
if (strpos($path, '..' . DIRECTORY_SEPARATOR) !== false &&
|
||||||
preg_match_all('#(([.]?[\\\\/])*([.][.])[\\\\/]([.]?[\\\\/])*)+#u', $path, $match)
|
preg_match_all('#[\\\\/]([.][.][\\\\/])+#u', $path, $match)
|
||||||
) {
|
) {
|
||||||
$counts = array();
|
$counts = array();
|
||||||
foreach ($match[ 0 ] as $m) {
|
foreach ($match[ 0 ] as $m) {
|
||||||
@@ -1068,13 +1074,13 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
}
|
}
|
||||||
sort($counts);
|
sort($counts);
|
||||||
foreach ($counts as $count) {
|
foreach ($counts as $count) {
|
||||||
$path = preg_replace('#(([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count .
|
$path = preg_replace('#([\\\\/]+[^\\\\/]+){' . $count .
|
||||||
'}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . '})(?=[^.])#u',
|
'}[\\\\/]+([.][.][\\\\/]+){' . $count . '}#u',
|
||||||
DIRECTORY_SEPARATOR,
|
DIRECTORY_SEPARATOR,
|
||||||
$path);
|
$path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $parts[ 'root' ] . $path;
|
return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -514,60 +514,39 @@ class Smarty_Security
|
|||||||
public function isTrustedResourceDir($filepath, $isConfig = null)
|
public function isTrustedResourceDir($filepath, $isConfig = null)
|
||||||
{
|
{
|
||||||
if ($this->_include_path_status !== $this->smarty->use_include_path) {
|
if ($this->_include_path_status !== $this->smarty->use_include_path) {
|
||||||
foreach ($this->_include_dir as $directory) {
|
$_dir = $this->smarty->use_include_path ? $this->smarty->ext->_getIncludePath->getIncludePathDirs($this->smarty) : array();
|
||||||
unset($this->_resource_dir[ $directory ]);
|
if ($this->_include_dir !== $_dir) {
|
||||||
}
|
$this->_updateResourceDir($this->_include_dir, $_dir);
|
||||||
if ($this->smarty->use_include_path) {
|
$this->_include_dir = $_dir;
|
||||||
$this->_include_dir = array();
|
|
||||||
$_dirs = $this->smarty->ext->_getIncludePath->getIncludePathDirs($this->smarty);
|
|
||||||
foreach ($_dirs as $directory) {
|
|
||||||
$this->_include_dir[] = $directory;
|
|
||||||
$this->_resource_dir[ $directory ] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$this->_include_path_status = $this->smarty->use_include_path;
|
$this->_include_path_status = $this->smarty->use_include_path;
|
||||||
}
|
}
|
||||||
if ($isConfig !== true &&
|
if ($isConfig !== true) {
|
||||||
(!isset($this->smarty->_cache[ 'template_dir_new' ]) || $this->smarty->_cache[ 'template_dir_new' ])
|
|
||||||
) {
|
|
||||||
$_dir = $this->smarty->getTemplateDir();
|
$_dir = $this->smarty->getTemplateDir();
|
||||||
if ($this->_template_dir !== $_dir) {
|
if ($this->_template_dir !== $_dir) {
|
||||||
foreach ($this->_template_dir as $directory) {
|
$this->_updateResourceDir($this->_template_dir, $_dir);
|
||||||
unset($this->_resource_dir[ $directory ]);
|
|
||||||
}
|
|
||||||
foreach ($_dir as $directory) {
|
|
||||||
$this->_resource_dir[ $directory ] = true;
|
|
||||||
}
|
|
||||||
$this->_template_dir = $_dir;
|
$this->_template_dir = $_dir;
|
||||||
}
|
}
|
||||||
$this->smarty->_cache[ 'template_dir_new' ] = false;
|
|
||||||
}
|
}
|
||||||
if ($isConfig !== false &&
|
if ($isConfig !== false) {
|
||||||
(!isset($this->smarty->_cache[ 'config_dir_new' ]) || $this->smarty->_cache[ 'config_dir_new' ])
|
|
||||||
) {
|
|
||||||
$_dir = $this->smarty->getConfigDir();
|
$_dir = $this->smarty->getConfigDir();
|
||||||
if ($this->_config_dir !== $_dir) {
|
if ($this->_config_dir !== $_dir) {
|
||||||
foreach ($this->_config_dir as $directory) {
|
$this->_updateResourceDir($this->_config_dir, $_dir);
|
||||||
unset($this->_resource_dir[ $directory ]);
|
|
||||||
}
|
|
||||||
foreach ($_dir as $directory) {
|
|
||||||
$this->_resource_dir[ $directory ] = true;
|
|
||||||
}
|
|
||||||
$this->_config_dir = $_dir;
|
$this->_config_dir = $_dir;
|
||||||
}
|
}
|
||||||
$this->smarty->_cache[ 'config_dir_new' ] = false;
|
|
||||||
}
|
}
|
||||||
if ($this->_secure_dir !== (array) $this->secure_dir) {
|
if ($this->_secure_dir !== $this->secure_dir) {
|
||||||
foreach ($this->_secure_dir as $directory) {
|
$this->secure_dir = (array)$this->secure_dir;
|
||||||
unset($this->_resource_dir[ $directory ]);
|
foreach($this->secure_dir as $k => $d) {
|
||||||
|
$this->secure_dir[$k] = $this->smarty->_realpath($d.DIRECTORY_SEPARATOR,true);
|
||||||
}
|
}
|
||||||
foreach ((array) $this->secure_dir as $directory) {
|
$this->_updateResourceDir($this->_secure_dir, $this->secure_dir);
|
||||||
$directory = $this->smarty->_realpath($directory . DIRECTORY_SEPARATOR, true);
|
$this->_secure_dir = $this->secure_dir;
|
||||||
$this->_resource_dir[ $directory ] = true;
|
}
|
||||||
}
|
$addPath = $this->_checkDir($filepath, $this->_resource_dir);
|
||||||
$this->_secure_dir = (array) $this->secure_dir;
|
if ($addPath !== false) {
|
||||||
|
$this->_resource_dir = array_merge($this->_resource_dir, $addPath);
|
||||||
}
|
}
|
||||||
$this->_resource_dir = $this->_checkDir($filepath, $this->_resource_dir);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,40 +601,64 @@ class Smarty_Security
|
|||||||
$this->_php_resource_dir[ $directory ] = true;
|
$this->_php_resource_dir[ $directory ] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$addPath = $this->_checkDir($filepath, $this->_php_resource_dir);
|
||||||
$this->_php_resource_dir =
|
if ($addPath !== false) {
|
||||||
$this->_checkDir($this->smarty->_realpath($filepath, true), $this->_php_resource_dir);
|
$this->_php_resource_dir = array_merge($this->_php_resource_dir, $addPath);
|
||||||
return true;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove old directories and its sub folders, add new directories
|
||||||
|
*
|
||||||
|
* @param array $oldDir
|
||||||
|
* @param array $newDir
|
||||||
|
*/
|
||||||
|
private function _updateResourceDir($oldDir, $newDir) {
|
||||||
|
foreach ($oldDir as $directory) {
|
||||||
|
$directory = $this->smarty->_realpath($directory, true);
|
||||||
|
$length = strlen($directory);
|
||||||
|
foreach ($this->_resource_dir as $dir) {
|
||||||
|
if (substr($dir, 0,$length) === $directory) {
|
||||||
|
unset($this->_resource_dir[ $dir ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($newDir as $directory) {
|
||||||
|
$directory = $this->smarty->_realpath($directory, true);
|
||||||
|
$this->_resource_dir[ $directory ] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Check if file is inside a valid directory
|
* Check if file is inside a valid directory
|
||||||
*
|
*
|
||||||
* @param string $filepath
|
* @param string $filepath
|
||||||
* @param array $dirs valid directories
|
* @param array $dirs valid directories
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array|bool
|
||||||
* @throws \SmartyException
|
* @throws \SmartyException
|
||||||
*/
|
*/
|
||||||
private function _checkDir($filepath, $dirs)
|
private function _checkDir($filepath, $dirs)
|
||||||
{
|
{
|
||||||
|
$directory = dirname($filepath) . DIRECTORY_SEPARATOR;
|
||||||
|
if (isset($dirs[ $directory ])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$filepath = $this->smarty->_realpath($filepath, true);
|
||||||
$directory = dirname($filepath) . DIRECTORY_SEPARATOR;
|
$directory = dirname($filepath) . DIRECTORY_SEPARATOR;
|
||||||
$_directory = array();
|
$_directory = array();
|
||||||
while (true) {
|
while (true) {
|
||||||
// remember the directory to add it to _resource_dir in case we're successful
|
// test if the directory is trusted
|
||||||
$_directory[ $directory ] = true;
|
|
||||||
// test if the directory is trusted
|
|
||||||
if (isset($dirs[ $directory ])) {
|
if (isset($dirs[ $directory ])) {
|
||||||
// merge sub directories of current $directory into _resource_dir to speed up subsequent lookup
|
return $_directory;
|
||||||
$dirs = array_merge($dirs, $_directory);
|
|
||||||
|
|
||||||
return $dirs;
|
|
||||||
}
|
}
|
||||||
// abort if we've reached root
|
// abort if we've reached root
|
||||||
if (!preg_match('#[\\\/][^\\\/]+[\\\/]$#', $directory)) {
|
if (!preg_match('#[\\\/][^\\\/]+[\\\/]$#', $directory)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// bubble up one level
|
// remember the directory to add it to _resource_dir in case we're successful
|
||||||
|
$_directory[ $directory ] = true;
|
||||||
|
// bubble up one level
|
||||||
$directory = preg_replace('#[\\\/][^\\\/]+[\\\/]$#', DIRECTORY_SEPARATOR, $directory);
|
$directory = preg_replace('#[\\\/][^\\\/]+[\\\/]$#', DIRECTORY_SEPARATOR, $directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user