diff options
-rw-r--r-- | system/core/Common.php | 18 | ||||
-rw-r--r-- | system/database/drivers/ibase/ibase_driver.php | 6 | ||||
-rw-r--r-- | system/libraries/Encrypt.php | 2 | ||||
-rw-r--r-- | system/libraries/Parser.php | 66 | ||||
-rw-r--r-- | system/libraries/Upload.php | 22 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 3 |
6 files changed, 55 insertions, 62 deletions
diff --git a/system/core/Common.php b/system/core/Common.php index 752a2e7f1..b5a696c68 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -690,16 +690,20 @@ if ( ! function_exists('remove_invisible_characters')) if ( ! function_exists('html_escape')) { /** - * Returns HTML escaped variable + * Returns HTML escaped variable. * - * @param mixed - * @return mixed + * @param mixed $var The input string or array of strings to be escaped. + * @param bool $double_encode $double_encode set to FALSE prevents escaping twice. + * @return mixed The escaped string or array of strings as a result. */ - function html_escape($var) + function html_escape($var, $double_encode = TRUE) { - return is_array($var) - ? array_map('html_escape', $var) - : htmlspecialchars($var, ENT_QUOTES, config_item('charset')); + if (is_array($var)) + { + return array_map('html_escape', $var, array_fill(0, count($var), $double_encode)); + } + + return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode); } } diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php index b19985c37..f4e5aef7c 100644 --- a/system/database/drivers/ibase/ibase_driver.php +++ b/system/database/drivers/ibase/ibase_driver.php @@ -219,11 +219,11 @@ class CI_DB_ibase_driver extends CI_DB { */ protected function _list_tables($prefix_limit = FALSE) { - $sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\''; + $sql = 'SELECT TRIM("RDB$RELATION_NAME") AS TABLE_NAME FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\''; if ($prefix_limit !== FALSE && $this->dbprefix !== '') { - return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " + return $sql.' AND TRIM("RDB$RELATION_NAME") AS TABLE_NAME LIKE \''.$this->escape_like_str($this->dbprefix)."%' " .sprintf($this->_like_escape_str, $this->_like_escape_chr); } @@ -242,7 +242,7 @@ class CI_DB_ibase_driver extends CI_DB { */ protected function _list_columns($table = '') { - return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table); + return 'SELECT TRIM("RDB$FIELD_NAME") AS COLUMN_NAME FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table); } // -------------------------------------------------------------------- diff --git a/system/libraries/Encrypt.php b/system/libraries/Encrypt.php index 2541a4467..995bf0bbe 100644 --- a/system/libraries/Encrypt.php +++ b/system/libraries/Encrypt.php @@ -29,7 +29,7 @@ defined('BASEPATH') OR exit('No direct script access allowed'); /** * CodeIgniter Encryption Class * - * Provides two-way keyed encoding using XOR Hashing and Mcrypt + * Provides two-way keyed encoding using Mcrypt * * @package CodeIgniter * @subpackage Libraries diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php index d23a53423..8d802d2aa 100644 --- a/system/libraries/Parser.php +++ b/system/libraries/Parser.php @@ -128,13 +128,20 @@ class CI_Parser { return FALSE; } + $replace = array(); foreach ($data as $key => $val) { - $template = is_array($val) + $replace = array_merge( + $replace, + is_array($val) ? $this->_parse_pair($key, $val, $template) - : $template = $this->_parse_single($key, (string) $val, $template); + : $this->_parse_single($key, (string) $val, $template) + ); } + unset($data); + $template = strtr($template, $replace); + if ($return === FALSE) { $this->CI->output->append_output($template); @@ -170,7 +177,7 @@ class CI_Parser { */ protected function _parse_single($key, $val, $string) { - return str_replace($this->l_delim.$key.$this->r_delim, (string) $val, $string); + return array($this->l_delim.$key.$this->r_delim => (string) $val); } // -------------------------------------------------------------------- @@ -187,50 +194,43 @@ class CI_Parser { */ protected function _parse_pair($variable, $data, $string) { - if (FALSE === ($matches = $this->_match_pair($string, $variable))) - { - return $string; - } + $replace = array(); + preg_match_all( + '#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s', + $string, + $matches, + PREG_SET_ORDER + ); - $str = ''; - $search = $replace = array(); foreach ($matches as $match) { $str = ''; foreach ($data as $row) { - $temp = $match[1]; + $temp = array(); foreach ($row as $key => $val) { - $temp = is_array($val) - ? $this->_parse_pair($key, $val, $temp) - : $this->_parse_single($key, $val, $temp); + if (is_array($val)) + { + $pair = $this->_parse_pair($key, $val, $temp); + if ( ! empty($pair)) + { + $temp = array_merge($temp, $pair); + } + + continue; + } + + $temp[$this->l_delim.$key.$this->r_delim] = $val; } - $str .= $temp; + $str .= strtr($match[1], $temp); } - $search[] = $match[0]; - $replace[] = $str; + $replace[$match[0]] = $str; } - return str_replace($search, $replace, $string); - } - - // -------------------------------------------------------------------- - - /** - * Matches a variable pair - * - * @param string $string - * @param string $variable - * @return mixed - */ - protected function _match_pair($string, $variable) - { - return preg_match_all('|'.preg_quote($this->l_delim).$variable.preg_quote($this->r_delim).'(.+?)'.preg_quote($this->l_delim).'/'.$variable.preg_quote($this->r_delim).'|s', - $string, $match, PREG_SET_ORDER) - ? $match : FALSE; + return $replace; } } diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index 7946111cc..49c69a32c 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -1158,28 +1158,14 @@ class CI_Upload { */ protected function _prep_filename($filename) { - if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR strpos($filename, '.') === FALSE) + if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR ($ext_pos = strrpos($filename, '.')) === FALSE) { return $filename; } - $parts = explode('.', $filename); - $ext = array_pop($parts); - $filename = array_shift($parts); - - foreach ($parts as $part) - { - if ( ! in_array(strtolower($part), $this->allowed_types) OR ! isset($this->_mimes[strtolower($part)])) - { - $filename .= '.'.$part.'_'; - } - else - { - $filename .= '.'.$part; - } - } - - return $filename.'.'.$ext; + $ext = substr($filename, $ext_pos); + $filename = substr($filename, 0, $ext_pos); + return str_replace('.', '_', $filename).$ext; } // -------------------------------------------------------------------- diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 6619ae971..5c233efac 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -306,6 +306,7 @@ Release Date: Not Released - Added a ``$reset`` parameter to method ``initialize()``. - Removed method ``clean_file_name()`` and its usage in favor of :doc:`Security Library <libraries/security>`'s ``sanitize_filename()``. - Removed method ``mimes_types()``. + - Changed ``CI_Upload::_prep_filename()`` to simply replace all (but the last) dots in the filename with underscores, instead of suffixing them. - :doc:`Calendar Library <libraries/calendar>` changes include: @@ -489,6 +490,7 @@ Release Date: Not Released - Removed the third (`$php_error`) argument from function :func:`log_message()`. - Changed internal function ``load_class()`` to accept a constructor parameter instead of (previously unused) class name prefix. - Removed default parameter value of :func:`is_php()`. + - Added a second argument ``$double_encode`` to :func:`html_escape()`. - :doc:`Output Library <libraries/output>` changes include: @@ -742,6 +744,7 @@ Bug fixes for 3.0 - Fixed a bug where ``CI_Xmlrpcs::parseRequest()`` could fail if ``$HTTP_RAW_POST_DATA`` is not populated. - Fixed a bug in :doc:`Zip Library <libraries/zip>` internal method ``_get_mod_time()`` where it was not parsing result returned by ``filemtime()``. - Fixed a bug (#3161) - :doc:`Cache Library <libraries/cache>` methods `increment()`, `decrement()` didn't auto-create non-existent items when using redis and/or file storage. +- Fixed a bug (#3189) - :doc:`Parser Library <libraries/parser>` used double replacement on ``key->value`` pairs, exposing a potential template injection vulnerability. Version 2.2.0 ============= |