summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--system/core/Common.php18
-rw-r--r--system/database/drivers/ibase/ibase_driver.php6
-rw-r--r--system/libraries/Encrypt.php2
-rw-r--r--system/libraries/Parser.php66
-rw-r--r--system/libraries/Upload.php22
-rw-r--r--user_guide_src/source/changelog.rst3
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
=============