Update to CodeIgniter 3.19
This commit is contained in:
@@ -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]',
|
||||
'<!--' => '<!--',
|
||||
'-->' => '-->',
|
||||
'<![CDATA[' => '<![CDATA[',
|
||||
'<comment>' => '<comment>'
|
||||
'document.cookie' => '[removed]',
|
||||
'(document).cookie' => '[removed]',
|
||||
'document.write' => '[removed]',
|
||||
'(document).write' => '[removed]',
|
||||
'.parentNode' => '[removed]',
|
||||
'.innerHTML' => '[removed]',
|
||||
'-moz-binding' => '[removed]',
|
||||
'<!--' => '<!--',
|
||||
'-->' => '-->',
|
||||
'<![CDATA[' => '<![CDATA[',
|
||||
'<comment>' => '<comment>',
|
||||
'<%' => '<%'
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -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: <blink>
|
||||
*/
|
||||
$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`\\3`',
|
||||
$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[':'] = ':';
|
||||
$_entities['('] = '(';
|
||||
$_entities[')'] = ')';
|
||||
$_entities["\n"] = '
';
|
||||
$_entities["\t"] = '	';
|
||||
}
|
||||
}
|
||||
|
||||
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[':'] = ':';
|
||||
$_entities['('] = '(';
|
||||
$_entities[')'] = ')';
|
||||
$_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])
|
||||
),
|
||||
|
Reference in New Issue
Block a user