Archived
1
0

Update to CodeIgniter 3.19

This commit is contained in:
Marcel
2018-12-29 16:16:49 +01:00
parent b036b4d36e
commit d09ee2788d
159 changed files with 2508 additions and 1910 deletions

View File

@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014 - 2016, British Columbia Institute of Technology
* Copyright (c) 2014 - 2018, British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
* @package CodeIgniter
* @author EllisLab Dev Team
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
* @copyright Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
* @license http://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 1.0.0
@@ -133,15 +133,18 @@ class CI_Security {
* @var array
*/
protected $_never_allowed_str = array(
'document.cookie' => '[removed]',
'document.write' => '[removed]',
'.parentNode' => '[removed]',
'.innerHTML' => '[removed]',
'-moz-binding' => '[removed]',
'<!--' => '&lt;!--',
'-->' => '--&gt;',
'<![CDATA[' => '&lt;![CDATA[',
'<comment>' => '&lt;comment&gt;'
'document.cookie' => '[removed]',
'(document).cookie' => '[removed]',
'document.write' => '[removed]',
'(document).write' => '[removed]',
'.parentNode' => '[removed]',
'.innerHTML' => '[removed]',
'-moz-binding' => '[removed]',
'<!--' => '&lt;!--',
'-->' => '--&gt;',
'<![CDATA[' => '&lt;![CDATA[',
'<comment>' => '&lt;comment&gt;',
'<%' => '&lt;&#37;'
);
/**
@@ -151,7 +154,7 @@ class CI_Security {
*/
protected $_never_allowed_regex = array(
'javascript\s*:',
'(document|(document\.)?window)\.(location|on\w*)',
'(\(?document\)?|\(?window\)?(\.document)?)\.(location|on\w*)',
'expression\s*(\(|&\#40;)', // CSS and IE
'vbscript\s*:', // IE, surprise!
'wscript\s*:', // IE
@@ -223,14 +226,11 @@ class CI_Security {
}
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
{
$this->csrf_show_error();
}
// Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
$valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
&& hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);
// We kill this since we're done and we don't want to polute the _POST array
// We kill this since we're done and we don't want to pollute the _POST array
unset($_POST[$this->_csrf_token_name]);
// Regenerate on every submission?
@@ -244,6 +244,11 @@ class CI_Security {
$this->_csrf_set_hash();
$this->csrf_set_cookie();
if ($valid !== TRUE)
{
$this->csrf_show_error();
}
log_message('info', 'CSRF token verified');
return $this;
}
@@ -351,9 +356,9 @@ class CI_Security {
// Is the string an array?
if (is_array($str))
{
while (list($key) = each($str))
foreach ($str as $key => &$value)
{
$str[$key] = $this->xss_clean($str[$key]);
$str[$key] = $this->xss_clean($value);
}
return $str;
@@ -371,11 +376,17 @@ class CI_Security {
*
* Note: Use rawurldecode() so it does not remove plus signs
*/
do
if (stripos($str, '%') !== false)
{
$str = rawurldecode($str);
do
{
$oldstr = $str;
$str = rawurldecode($str);
$str = preg_replace_callback('#%(?:\s*[0-9a-f]){2,}#i', array($this, '_urldecodespaces'), $str);
}
while ($oldstr !== $str);
unset($oldstr);
}
while (preg_match('/%[0-9a-f]{2,}/i', $str));
/*
* Convert character entities to ASCII
@@ -466,7 +477,7 @@ class CI_Security {
if (preg_match('/<a/i', $str))
{
$str = preg_replace_callback('#<a[^a-z0-9>]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
$str = preg_replace_callback('#<a(?:rea)?[^a-z0-9>]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
}
if (preg_match('/<img/i', $str))
@@ -492,7 +503,7 @@ class CI_Security {
* Becomes: &lt;blink&gt;
*/
$pattern = '#'
.'<((?<slash>/*\s*)(?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)' // tag start and name, followed by a non-tag character
.'<((?<slash>/*\s*)((?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)|.+)' // tag start and name, followed by a non-tag character
.'[^\s\042\047a-z0-9>/=]*' // a valid attribute character immediately after the tag would count as a separator
// optional attributes
.'(?<attributes>(?:[\s\042\047/=]*' // non-attribute characters, excluding > (tag close) for obvious reasons
@@ -533,6 +544,14 @@ class CI_Security {
$str
);
// Same thing, but for "tag functions" (e.g. eval`some code`)
// See https://github.com/bcit-ci/CodeIgniter/issues/5420
$str = preg_replace(
'#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)`(.*?)`#si',
'\\1\\2&#96;\\3&#96;',
$str
);
// Final clean up
// This adds a bit of extra precaution in case
// something got through the above filters
@@ -669,6 +688,22 @@ class CI_Security {
? ENT_COMPAT | ENT_HTML5
: ENT_COMPAT;
if ( ! isset($_entities))
{
$_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, $flag, $charset));
// If we're not on PHP 5.4+, add the possibly dangerous HTML 5
// entities to the array manually
if ($flag === ENT_COMPAT)
{
$_entities[':'] = '&colon;';
$_entities['('] = '&lpar;';
$_entities[')'] = '&rpar;';
$_entities["\n"] = '&NewLine;';
$_entities["\t"] = '&Tab;';
}
}
do
{
$str_compare = $str;
@@ -676,27 +711,6 @@ class CI_Security {
// Decode standard entities, avoiding false positives
if (preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches))
{
if ( ! isset($_entities))
{
$_entities = array_map(
'strtolower',
is_php('5.3.4')
? get_html_translation_table(HTML_ENTITIES, $flag, $charset)
: get_html_translation_table(HTML_ENTITIES, $flag)
);
// If we're not on PHP 5.4+, add the possibly dangerous HTML 5
// entities to the array manually
if ($flag === ENT_COMPAT)
{
$_entities[':'] = '&colon;';
$_entities['('] = '&lpar;';
$_entities[')'] = '&rpar;';
$_entities["\n"] = '&newline;';
$_entities["\t"] = '&tab;';
}
}
$replace = array();
$matches = array_unique(array_map('strtolower', $matches[0]));
foreach ($matches as &$match)
@@ -707,7 +721,7 @@ class CI_Security {
}
}
$str = str_ireplace(array_keys($replace), array_values($replace), $str);
$str = str_replace(array_keys($replace), array_values($replace), $str);
}
// Decode numeric & UTF16 two byte entities
@@ -716,6 +730,11 @@ class CI_Security {
$flag,
$charset
);
if ($flag === ENT_COMPAT)
{
$str = str_replace(array_values($_entities), array_keys($_entities), $str);
}
}
while ($str_compare !== $str);
return $str;
@@ -774,6 +793,24 @@ class CI_Security {
// ----------------------------------------------------------------
/**
* URL-decode taking spaces into account
*
* @see https://github.com/bcit-ci/CodeIgniter/issues/4877
* @param array $matches
* @return string
*/
protected function _urldecodespaces($matches)
{
$input = $matches[0];
$nospaces = preg_replace('#\s+#', '', $input);
return ($nospaces === $input)
? $input
: rawurldecode($nospaces);
}
// ----------------------------------------------------------------
/**
* Compact Exploded Words
*
@@ -803,7 +840,7 @@ class CI_Security {
protected function _sanitize_naughty_html($matches)
{
static $naughty_tags = array(
'alert', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',
'alert', 'area', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',
'blink', 'body', 'embed', 'expression', 'form', 'frameset', 'frame', 'head', 'html', 'ilayer',
'iframe', 'input', 'button', 'select', 'isindex', 'layer', 'link', 'meta', 'keygen', 'object',
'plaintext', 'style', 'script', 'textarea', 'title', 'math', 'video', 'svg', 'xml', 'xss'
@@ -826,7 +863,7 @@ class CI_Security {
// For other tags, see if their attributes are "evil" and strip those
elseif (isset($matches['attributes']))
{
// We'll store the already fitlered attributes here
// We'll store the already filtered attributes here
$attributes = array();
// Attribute-catching pattern
@@ -842,7 +879,7 @@ class CI_Security {
// Each iteration filters a single attribute
do
{
// Strip any non-alpha characters that may preceed an attribute.
// Strip any non-alpha characters that may precede an attribute.
// Browsers often parse these incorrectly and that has been a
// of numerous XSS issues we've had.
$matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']);
@@ -900,7 +937,7 @@ class CI_Security {
return str_replace(
$match[1],
preg_replace(
'#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
'#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;|`|&\#96;)|javascript:|livescript:|mocha:|charset=|window\.|\(?document\)?\.|\.cookie|<script|<xss|d\s*a\s*t\s*a\s*:)#si',
'',
$this->_filter_attributes($match[1])
),
@@ -928,7 +965,7 @@ class CI_Security {
return str_replace(
$match[1],
preg_replace(
'#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
'#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;|`|&\#96;)|javascript:|livescript:|mocha:|charset=|window\.|\(?document\)?\.|\.cookie|<script|<xss|base64\s*,)#si',
'',
$this->_filter_attributes($match[1])
),