diff options
Diffstat (limited to 'system/core/Security.php')
-rwxr-xr-x | system/core/Security.php | 131 |
1 files changed, 70 insertions, 61 deletions
diff --git a/system/core/Security.php b/system/core/Security.php index ac39ce97b..4593a1090 100755 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -41,14 +41,14 @@ class CI_Security { * * @var string */ - protected $_xss_hash = ''; + protected $_xss_hash = ''; /** * Random Hash for Cross Site Request Forgery Protection Cookie * * @var string */ - protected $_csrf_hash = ''; + protected $_csrf_hash = ''; /** * Expiration time for Cross Site Request Forgery Protection Cookie @@ -56,39 +56,39 @@ class CI_Security { * * @var int */ - protected $_csrf_expire = 7200; + protected $_csrf_expire = 7200; /** * Token name for Cross Site Request Forgery Protection Cookie * * @var string */ - protected $_csrf_token_name = 'ci_csrf_token'; + protected $_csrf_token_name = 'ci_csrf_token'; /** * Cookie name for Cross Site Request Forgery Protection Cookie * * @var string */ - protected $_csrf_cookie_name = 'ci_csrf_token'; + protected $_csrf_cookie_name = 'ci_csrf_token'; /** * List of never allowed strings * * @var array */ - protected $_never_allowed_str = array( - 'document.cookie' => '[removed]', - 'document.write' => '[removed]', - '.parentNode' => '[removed]', - '.innerHTML' => '[removed]', - 'window.location' => '[removed]', - '-moz-binding' => '[removed]', - '<!--' => '<!--', - '-->' => '-->', - '<![CDATA[' => '<![CDATA[', - '<comment>' => '<comment>' - ); + protected $_never_allowed_str = array( + 'document.cookie' => '[removed]', + 'document.write' => '[removed]', + '.parentNode' => '[removed]', + '.innerHTML' => '[removed]', + 'window.location' => '[removed]', + '-moz-binding' => '[removed]', + '<!--' => '<!--', + '-->' => '-->', + '<![CDATA[' => '<![CDATA[', + '<comment>' => '<comment>' + ); /** * List of never allowed regex replacement @@ -96,12 +96,18 @@ class CI_Security { * @var array */ protected $_never_allowed_regex = array( - 'javascript\s*:', - 'expression\s*(\(|&\#40;)', // CSS and IE - 'vbscript\s*:', // IE, surprise! - 'Redirect\s+302' - ); + 'javascript\s*:', + 'expression\s*(\(|&\#40;)', // CSS and IE + 'vbscript\s*:', // IE, surprise! + 'Redirect\s+302', + "([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?" + ); + /** + * Initialize security class + * + * @return void + */ public function __construct() { // Is CSRF protection enabled? @@ -156,7 +162,7 @@ class CI_Security { // Do the tokens exist in both the _POST and _COOKIE arrays? if ( ! isset($_POST[$this->_csrf_token_name]) OR ! isset($_COOKIE[$this->_csrf_cookie_name]) - OR $_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match? + OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match? { $this->csrf_show_error(); } @@ -185,6 +191,7 @@ class CI_Security { * Set Cross Site Request Forgery Protection Cookie * * @return object + * @codeCoverageIgnore */ public function csrf_set_cookie() { @@ -197,11 +204,11 @@ class CI_Security { } setcookie( - $this->_csrf_cookie_name, - $this->_csrf_hash, - $expire, - config_item('cookie_path'), - config_item('cookie_domain'), + $this->_csrf_cookie_name, + $this->_csrf_hash, + $expire, + config_item('cookie_path'), + config_item('cookie_domain'), $secure_cookie, config_item('cookie_httponly') ); @@ -362,9 +369,10 @@ class CI_Security { * These words are compacted back to their correct state. */ $words = array( - 'javascript', 'expression', 'vbscript', 'script', - 'applet', 'alert', 'document', 'write', 'cookie', 'window' - ); + 'javascript', 'expression', 'vbscript', 'script', 'base64', + 'applet', 'alert', 'document', 'write', 'cookie', 'window' + ); + foreach ($words as $word) { @@ -400,7 +408,7 @@ class CI_Security { $str = preg_replace('#<(/*)(script|xss)(.*?)\>#si', '[removed]', $str); } } - while($original != $str); + while($original !== $str); unset($original); @@ -467,7 +475,7 @@ class CI_Security { */ public function xss_hash() { - if ($this->_xss_hash == '') + if ($this->_xss_hash === '') { mt_srand(); $this->_xss_hash = md5(time() + mt_rand(0, 1999999999)); @@ -522,23 +530,23 @@ class CI_Security { public function sanitize_filename($str, $relative_path = FALSE) { $bad = array( - '../', '<!--', '-->', '<', '>', - "'", '"', '&', '$', '#', - '{', '}', '[', ']', '=', - ';', '?', '%20', '%22', - '%3c', // < - '%253c', // < - '%3e', // > - '%0e', // > - '%28', // ( - '%29', // ) - '%2528', // ( - '%26', // & - '%24', // $ - '%3f', // ? - '%3b', // ; - '%3d' // = - ); + '../', '<!--', '-->', '<', '>', + "'", '"', '&', '$', '#', + '{', '}', '[', ']', '=', + ';', '?', '%20', '%22', + '%3c', // < + '%253c', // < + '%3e', // > + '%0e', // > + '%28', // ( + '%29', // ) + '%2528', // ( + '%26', // & + '%24', // $ + '%3f', // ? + '%3b', // ; + '%3d' // = + ); if ( ! $relative_path) { @@ -558,8 +566,8 @@ class CI_Security { * Callback function for xss_clean() to remove whitespace from * things like j a v a s c r i p t * - * @param type - * @return type + * @param array + * @return string */ protected function _compact_exploded_words($matches) { @@ -568,8 +576,8 @@ class CI_Security { // -------------------------------------------------------------------- - /* - * Remove Evil HTML Attributes (like evenhandlers and style) + /** + * Remove Evil HTML Attributes (like event handlers and style) * * It removes the evil attribute and either: * - Everything up until a space @@ -602,10 +610,11 @@ class CI_Security { $attribs = array(); // find occurrences of illegal attribute strings without quotes - preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s]*)/is', $str, $matches, PREG_SET_ORDER); + preg_match_all('/('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', $str, $matches, PREG_SET_ORDER); foreach ($matches as $attr) { + $attribs[] = preg_quote($attr[0], '/'); } @@ -620,7 +629,7 @@ class CI_Security { // 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$5', $str, -1, $count); + $str = preg_replace('/<(\/?[^><]+?)([^A-Za-z<>\-])(.*?)('.implode('|', $attribs).')(.*?)([\s><])([><]*)/i', '<$1 $3$5$6$7', $str, -1, $count); } } while ($count); @@ -661,7 +670,7 @@ class CI_Security { protected function _js_link_removal($match) { return str_replace($match[1], - preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si', + preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si', '', $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1])) ), @@ -801,7 +810,7 @@ class CI_Security { foreach ($this->_never_allowed_regex as $regex) { - $str = preg_replace('#'.$regex.'#i', '[removed]', $str); + $str = preg_replace('#'.$regex.'#is', '[removed]', $str); } return $str; @@ -816,14 +825,14 @@ class CI_Security { */ protected function _csrf_set_hash() { - if ($this->_csrf_hash == '') + if ($this->_csrf_hash === '') { // If the cookie exists we will use it's value. // We don't necessarily want to regenerate it with // each page load since a page could contain embedded // sub-pages causing this feature to fail if (isset($_COOKIE[$this->_csrf_cookie_name]) && - $_COOKIE[$this->_csrf_cookie_name] != '') + preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1) { return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; } @@ -838,4 +847,4 @@ class CI_Security { } /* End of file Security.php */ -/* Location: ./system/core/Security.php */ +/* Location: ./system/core/Security.php */
\ No newline at end of file |