CVE-2018-13982 (PHP, published 2018-09-18T21:29Z)
Description: value: Smarty_Security::isTrustedResourceDir() in Smarty before 3.1.33 is prone to a path traversal vulnerability due to insufficient template code sanitization. This allows attackers controlling the executed template code to bypass the trusted directory security restriction and read arbitrary files.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/smarty-php/smarty
Files changed:
libs/Smarty.class.php
libs/sysplugins/smarty_security.php
Commit message: - bugfix  regarding Security Vulnerability did not solve the problem under Linux


Vulnerable code:
        static $nds = null;
        static $sepDotSep = null;
         static $sepSep =null;
        if (!isset($nds)) {
            $nds = array('/' => '\\', '\\' => '/');
            $sepDotSep = DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR;
            $sepSep = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
        }
        $path = str_replace(array($nds[DIRECTORY_SEPARATOR], $sepDotSep), DIRECTORY_SEPARATOR, $path);
       // remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns
        $path = str_replace(array($sepDotSep,$sepSep), DIRECTORY_SEPARATOR, $path);
        // resolve '..DIRECTORY_SEPARATOR' pattern, smallest first
        if (strpos($path, '..' . DIRECTORY_SEPARATOR) !== false &&
            preg_match_all('#[\\\\/]([.][.][\\\\/])+#u', $path, $match)
        ) {
            $counts = array();
            foreach ($match[ 0 ] as $m) {
                $counts[] = (int)((strlen($m) - 1) / 3);
            }
            sort($counts);
            foreach ($counts as $count) {
                $path = preg_replace('#([\\\\/]+[^\\\\/]+){' . $count .
                                     '}[\\\\/]+([.][.][\\\\/]+){' . $count . '}#u',
                                     DIRECTORY_SEPARATOR,
                                     $path);
            }
        }
        } else if (isset($this->_cache[ $name ])) {
        } else if (in_array($name, $this->obsoleteProperties)) {
        }
        } else if (in_array($name, $this->obsoleteProperties)) {
        }
            $directory = preg_replace('#[\\\\/][^\\\\/]+[\\\\/]$#', '/', $directory);

Fixed code:
        $nds = array('/' => '\\', '\\' => '/');
        $path = str_replace(array($nds[DIRECTORY_SEPARATOR], DIRECTORY_SEPARATOR . '.' . DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $path);
        do {
            $path = preg_replace(
            array('#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'),
            DIRECTORY_SEPARATOR, $path, -1, $count);
        } while($count > 0);
        } else {if (isset($this->_cache[ $name ])) {
        } else {if (in_array($name, $this->obsoleteProperties)) {
        }}}
        } else {if (in_array($name, $this->obsoleteProperties)) {
        }}
            $directory = preg_replace('#[\\\\/][^\\\\/]+[\\\\/]$#', DIRECTORY_SEPARATOR, $directory);