diff options
-rwxr-xr-x | system/core/Security.php | 61 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 3 | ||||
-rw-r--r-- | user_guide_src/source/libraries/security.rst | 17 |
3 files changed, 72 insertions, 9 deletions
diff --git a/system/core/Security.php b/system/core/Security.php index bb0670500..bc224e7e3 100755 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -77,7 +77,7 @@ class CI_Security { * * @var string */ - protected $_xss_hash = ''; + protected $_xss_hash; /** * CSRF Hash @@ -86,7 +86,7 @@ class CI_Security { * * @var string */ - protected $_csrf_hash = ''; + protected $_csrf_hash; /** * CSRF Expire time @@ -227,7 +227,7 @@ class CI_Security { { // Nothing should last forever unset($_COOKIE[$this->_csrf_cookie_name]); - $this->_csrf_hash = ''; + $this->_csrf_hash = NULL; } $this->_csrf_set_hash(); @@ -538,9 +538,12 @@ class CI_Security { */ public function xss_hash() { - if ($this->_xss_hash === '') + if ($this->_xss_hash === NULL) { - $this->_xss_hash = md5(uniqid(mt_rand())); + $rand = $this->get_random_bytes(16); + $this->_xss_hash = ($rand === FALSE) + ? md5(uniqid(mt_rand(), TRUE)) + : bin2hex($rand); } return $this->_xss_hash; @@ -549,6 +552,46 @@ class CI_Security { // -------------------------------------------------------------------- /** + * Get random bytes + * + * @param int $length Output length + * @return string + */ + public function get_random_bytes($length) + { + if (empty($length) OR ! ctype_digit($length)) + { + return FALSE; + } + + // Unfortunately, none of the following PRNGs is guaranteed to exist ... + if (defined(MCRYPT_DEV_URANDOM) && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE) + { + return $output; + } + + + if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE) + { + $output = fread($fp, $length); + fclose($fp); + if ($output !== FALSE) + { + return $output; + } + } + + if (function_exists('openssl_random_pseudo_bytes')) + { + return openssl_random_pseudo_bytes($length); + } + + return FALSE; + } + + // -------------------------------------------------------------------- + + /** * HTML Entities Decode * * A replacement for html_entity_decode() @@ -915,7 +958,7 @@ class CI_Security { */ protected function _csrf_set_hash() { - if ($this->_csrf_hash === '') + if ($this->_csrf_hash === NULL) { // If the cookie exists we will use its value. // We don't necessarily want to regenerate it with @@ -927,7 +970,11 @@ class CI_Security { return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; } - $this->_csrf_hash = md5(uniqid(mt_rand(), TRUE)); + $rand = $this->get_random_bytes(16); + $this->_csrf_hash = ($rand === FALSE) + ? md5(uniqid(mt_rand(), TRUE)) + : bin2hex($rand); + $this->csrf_set_cookie(); } diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 5c233efac..64a768977 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -508,9 +508,10 @@ Release Date: Not Released - :doc:`Security Library <libraries/security>` changes include: - - Added method ``strip_image_tags()``. - Added ``$config['csrf_regeneration']``, which makes CSRF token regeneration optional. - Added ``$config['csrf_exclude_uris']``, allowing for exclusion of URIs from the CSRF protection (regular expressions are supported). + - Added method ``strip_image_tags()``. + - Added method ``get_random_bytes()`` and switched CSRF & XSS token generation to use it. - Modified method ``sanitize_filename()`` to read a public ``$filename_bad_chars`` property for getting the invalid characters list. - Return status code of 403 instead of a 500 if CSRF protection is enabled but a token is missing from a request. diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst index c8d69d16f..0c51e342b 100644 --- a/user_guide_src/source/libraries/security.rst +++ b/user_guide_src/source/libraries/security.rst @@ -163,4 +163,19 @@ Class Reference This method acts a lot like PHP's own native ``html_entity_decode()`` function in ENT_COMPAT mode, only it tries to detect HTML entities that don't end in a semicolon because some browsers allow that. - If the ``$charset`` parameter is left empty, then your configured ``$config['charset']`` value will be used.
\ No newline at end of file + If the ``$charset`` parameter is left empty, then your configured ``$config['charset']`` value will be used. + + .. method:: get_random_bytes($length) + + :param int $length: Output length + :returns: A binary stream of random bytes or FALSE on failure + :rtype: string + + A convenience method for getting proper random bytes via ``mcrypt_create_iv()``, + ``/dev/urandom`` or ``openssl_random_pseudo_bytes()`` (in that order), if one + of them is available. + + Used for generating CSRF and XSS tokens. + + .. note:: The output is NOT guaranteed to be cryptographically secure, + just the best attempt at that.
\ No newline at end of file |