Skip to content

Commit

Permalink
Updates Codeigniter to 2.2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
Kovah committed Jun 7, 2016
1 parent ad9c943 commit 94d43c3
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 81 deletions.
2 changes: 1 addition & 1 deletion system/core/CodeIgniter.php
Expand Up @@ -34,7 +34,7 @@
* @var string
*
*/
define('CI_VERSION', '2.2.4');
define('CI_VERSION', '2.2.6');

/**
* CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
Expand Down
6 changes: 2 additions & 4 deletions system/core/Config.php
Expand Up @@ -67,12 +67,10 @@ function __construct()
// Set the base_url automatically if none was provided
if ($this->config['base_url'] == '')
{
// The regular expression is only a basic validation for a valid "Host" header.
// It's not exhaustive, only checks for valid characters.
if (isset($_SERVER['HTTP_HOST']) && preg_match('/^((\[[0-9a-f:]+\])|(\d{1,3}(\.\d{1,3}){3})|[a-z0-9\-\.]+)(:\d+)?$/i', $_SERVER['HTTP_HOST']))
if (isset($_SERVER['SERVER_ADDR']))
{
$base_url = (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off') ? 'http' : 'https';
$base_url .= '://'. $_SERVER['HTTP_HOST'];
$base_url .= '://'.$_SERVER['SERVER_ADDR'];
$base_url .= substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
}

Expand Down
165 changes: 96 additions & 69 deletions system/core/Security.php
Expand Up @@ -355,7 +355,7 @@ public function xss_clean($str, $is_image = FALSE)
$words = array(
'javascript', 'expression', 'vbscript', 'jscript', 'wscript',
'vbs', 'script', 'base64', 'applet', 'alert', 'document',
'write', 'cookie', 'window', 'confirm', 'prompt'
'write', 'cookie', 'window', 'confirm', 'prompt', 'eval'
);

foreach ($words as $word)
Expand Down Expand Up @@ -399,12 +399,8 @@ public function xss_clean($str, $is_image = FALSE)
}
}
while($original !== $str);

unset($original);

// Remove evil attributes such as style, onclick and xmlns
$str = $this->_remove_evil_attributes($str, $is_image);

/*
* Sanitize naughty HTML elements
*
Expand All @@ -414,8 +410,29 @@ public function xss_clean($str, $is_image = FALSE)
* So this: <blink>
* Becomes: &lt;blink&gt;
*/
$naughty = 'alert|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';
$str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
$pattern = '#'
.'<((?<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
.'[^\s\042\047>/=]+' // attribute characters
// optional attribute-value
.'(?:\s*=' // attribute-value separator
.'(?:[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*))' // single, double or non-quoted value
.')?' // end optional attribute-value group
.')*)' // end optional attributes group
.'[^>]*)(?<closeTag>\>)?#isS';

// Note: It would be nice to optimize this for speed, BUT
// only matching the naughty elements here results in
// false positives and in turn - vulnerabilities!
do
{
$old_str = $str;
$str = preg_replace_callback($pattern, array($this, '_sanitize_naughty_html'), $str);
}
while ($old_str !== $str);
unset($old_str);

/*
* Sanitize naughty scripting elements
Expand Down Expand Up @@ -626,82 +643,92 @@ protected function _compact_exploded_words($matches)

// --------------------------------------------------------------------

/*
* Remove Evil HTML Attributes (like evenhandlers and style)
/**
* Sanitize Naughty HTML
*
* It removes the evil attribute and either:
* - Everything up until a space
* For example, everything between the pipes:
* <a |style=document.write('hello');alert('world');| class=link>
* - Everything inside the quotes
* For example, everything between the pipes:
* <a |style="document.write('hello'); alert('world');"| class="link">
* Callback function for xss_clean() to remove naughty HTML elements
*
* @param string $str The string to check
* @param boolean $is_image TRUE if this is an image
* @return string The string with the evil attributes removed
* @param array
* @return string
*/
protected function _remove_evil_attributes($str, $is_image)
protected function _sanitize_naughty_html($matches)
{
// All javascript event handlers (e.g. onload, onclick, onmouseover), style, and xmlns
$evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime');
static $naughty_tags = array(
'alert', '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'
);

if ($is_image === TRUE)
static $evil_attributes = array(
'on\w+', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime'
);

// First, escape unclosed tags
if (empty($matches['closeTag']))
{
return '&lt;'.$matches[1];
}
// Is the element that we caught naughty? If so, escape it
elseif (in_array(strtolower($matches['tagName']), $naughty_tags, TRUE))
{
/*
* Adobe Photoshop puts XML metadata into JFIF images,
* including namespacing, so we have to allow this for images.
*/
unset($evil_attributes[array_search('xmlns', $evil_attributes)]);
return '&lt;'.$matches[1].'&gt;';
}
// For other tags, see if their attributes are "evil" and strip those
elseif (isset($matches['attributes']))
{
// We'll store the already fitlered attributes here
$attributes = array();

do {
$count = 0;
$attribs = array();
// Attribute-catching pattern
$attributes_pattern = '#'
.'(?<name>[^\s\042\047>/=]+)' // attribute characters
// optional attribute-value
.'(?:\s*=(?<value>[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*)))' // attribute-value separator
.'#i';

// find occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
preg_match_all('/(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is', $str, $matches, PREG_SET_ORDER);
// Blacklist pattern for evil attribute names
$is_evil_pattern = '#^('.implode('|', $evil_attributes).')$#i';

foreach ($matches as $attr)
// Each iteration filters a single attribute
do
{
$attribs[] = preg_quote($attr[0], '/');
}
// Strip any non-alpha characters that may preceed 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']);

// find occurrences of illegal attribute strings without quotes
preg_match_all('/(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER);
if ( ! preg_match($attributes_pattern, $matches['attributes'], $attribute, PREG_OFFSET_CAPTURE))
{
// No (valid) attribute found? Discard everything else inside the tag
break;
}

foreach ($matches as $attr)
{
$attribs[] = preg_quote($attr[0], '/');
}
if (
// Is it indeed an "evil" attribute?
preg_match($is_evil_pattern, $attribute['name'][0])
// Or does it have an equals sign, but no value and not quoted? Strip that too!
OR (trim($attribute['value'][0]) === '')
)
{
$attributes[] = 'xss=removed';
}
else
{
$attributes[] = $attribute[0][0];
}

// replace illegal attribute strings that are inside an html tag
if (count($attribs) > 0)
{
$str = preg_replace('/(<?)(\/?[^><]+?)([^A-Za-z<>\-])(.*?)('.implode('|', $attribs).')(.*?)([\s><]?)([><]*)/i', '$1$2 $4$6$7$8', $str, -1, $count);
$matches['attributes'] = substr($matches['attributes'], $attribute[0][1] + strlen($attribute[0][0]));
}
while ($matches['attributes'] !== '');

$attributes = empty($attributes)
? ''
: ' '.implode(' ', $attributes);
return '<'.$matches['slash'].$matches['tagName'].$attributes.'>';
}
while ($count);

return $str;
}

// --------------------------------------------------------------------

/**
* Sanitize Naughty HTML
*
* Callback function for xss_clean() to remove naughty HTML elements
*
* @param array
* @return string
*/
protected function _sanitize_naughty_html($matches)
{
return '&lt;'.$matches[1].$matches[2].$matches[3] // encode opening brace
// encode captured opening or closing brace to prevent recursive vectors:
.str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
return $matches[0];
}

// --------------------------------------------------------------------
Expand All @@ -724,7 +751,7 @@ protected function _js_link_removal($match)
preg_replace(
'#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
'',
$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
$this->_filter_attributes($match[1])
),
$match[0]
);
Expand All @@ -748,9 +775,9 @@ protected function _js_img_removal($match)
return str_replace(
$match[1],
preg_replace(
'#src=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
'#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
'',
$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
$this->_filter_attributes($match[1])
),
$match[0]
);
Expand Down Expand Up @@ -872,4 +899,4 @@ protected function _csrf_set_hash()
}

/* End of file Security.php */
/* Location: ./system/core/Security.php */
/* Location: ./system/core/Security.php */
103 changes: 96 additions & 7 deletions system/helpers/captcha_helper.php
Expand Up @@ -107,18 +107,93 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path =
// Do we have a "word" yet?
// -----------------------------------

if ($word == '')
{
// -----------------------------------
// Do we have a "word" yet?
// -----------------------------------

if (empty($word))
{
$word = '';
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$pool_length = strlen($pool);
$rand_max = $pool_length - 1;

$str = '';
for ($i = 0; $i < 8; $i++)
// PHP7 or a suitable polyfill
if (function_exists('random_int'))
{
$str .= substr($pool, mt_rand(0, strlen($pool) -1), 1);
try
{
for ($i = 0; $i < $word_length; $i++)
{
$word .= $pool[random_int(0, $rand_max)];
}
}
catch (Exception $e)
{
// This means fallback to the next possible
// alternative to random_int()
$word = '';
}
}
}

$word = $str;
}
if (empty($word))
{
// To avoid numerous get_random_bytes() calls, we'll
// just try fetching as much bytes as we need at once.
if (($bytes = _ci_captcha_get_random_bytes($pool_length)) !== FALSE)
{
$byte_index = $word_index = 0;
while ($word_index < $word_length)
{
if (($rand_index = unpack('C', $bytes[$byte_index++])) > $rand_max)
{
// Was this the last byte we have?
// If so, try to fetch more.
if ($byte_index === $pool_length)
{
// No failures should be possible if
// the first get_random_bytes() call
// didn't return FALSE, but still ...
for ($i = 0; $i < 5; $i++)
{
if (($bytes = _ci_captcha_get_random_bytes($pool_length)) === FALSE)
{
continue;
}

$byte_index = 0;
break;
}

if ($bytes === FALSE)
{
// Sadly, this means fallback to mt_rand()
$word = '';
break;
}
}

continue;
}

$word .= $pool[$rand_index];
$word_index++;
}
}
}

if (empty($word))
{
for ($i = 0; $i < $word_length; $i++)
{
$word .= $pool[mt_rand(0, $rand_max)];
}
}
elseif ( ! is_string($word))
{
$word = (string) $word;
}

// -----------------------------------
// Determine angle and position
Expand Down Expand Up @@ -239,6 +314,20 @@ function create_captcha($data = '', $img_path = '', $img_url = '', $font_path =

return array('word' => $word, 'time' => $now, 'image' => $img);
}

function _ci_captcha_get_random_bytes($length)
{
if (defined('MCRYPT_DEV_URANDOM'))
{
return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
}
elseif (function_exists('openssl_random_pseudo_bytes'))
{
return openssl_random_pseudo_bytes($length);
}

return FALSE;
}
}

// ------------------------------------------------------------------------
Expand Down

0 comments on commit 94d43c3

Please sign in to comment.