summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-08-27 15:26:23 +0200
committerAndrey Andreev <narf@devilix.net>2014-08-27 15:26:23 +0200
commit487ccc9c8a21cb6338aab7173b3adda194d29c26 (patch)
tree1c8661b246337fa71348d687795a8c500f7897b3
parentd4afe4a074015af109f1ab482f486d71e0b883f4 (diff)
Add CI_Security::get_random_bytes() for CSRF & XSS token generation
-rwxr-xr-xsystem/core/Security.php61
-rw-r--r--user_guide_src/source/changelog.rst3
-rw-r--r--user_guide_src/source/libraries/security.rst17
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