summaryrefslogtreecommitdiffstats
path: root/system/libraries/Session.php
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-05-31 20:00:05 +0200
committerAndrey Andreev <narf@devilix.net>2014-05-31 20:00:05 +0200
commit916b176594bcf175417423f33711ac0cbb4082e7 (patch)
treeba8e1fe4e8457005b1ca8635e7459159fea856e7 /system/libraries/Session.php
parentb4c693c50f54ecce1d0e2c1f203312f4bbb4af22 (diff)
Backport HMAC authentication for CI_Session
Diffstat (limited to 'system/libraries/Session.php')
-rw-r--r--system/libraries/Session.php56
1 files changed, 34 insertions, 22 deletions
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 53b914fbd..89c699765 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -144,24 +144,36 @@ class CI_Session {
return FALSE;
}
- // Decrypt the cookie data
- if ($this->sess_encrypt_cookie == TRUE)
+ // HMAC authentication
+ if (($len = strlen($session) - 40) <= 0)
{
- $session = $this->CI->encrypt->decode($session);
+ log_message('error', 'Session: The session cookie was not signed.');
+ return FALSE;
}
- else
+
+ // Check cookie authentication
+ $hmac = substr($session, $len);
+ $session = substr($session, 0, $len);
+
+ // Time-attack-safe comparison
+ $hmac_check = hash_hmac('sha1', $session, $this->encryption_key);
+ $diff = 0;
+ for ($i = 0; $i < 40; $i++)
{
- // encryption was not used, so we need to check the md5 hash
- $hash = substr($session, strlen($session)-32); // get last 32 chars
- $session = substr($session, 0, strlen($session)-32);
+ $diff |= ord($hmac[$i]) ^ ord($hmac_check[$i]);
+ }
- // Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
- {
- log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
- $this->sess_destroy();
- return FALSE;
- }
+ if ($diff !== 0)
+ {
+ log_message('error', 'Session: HMAC mismatch. The session cookie data did not match what was expected.');
+ $this->sess_destroy();
+ return FALSE;
+ }
+
+ // Decrypt the cookie data
+ if ($this->sess_encrypt_cookie == TRUE)
+ {
+ $session = $this->CI->encrypt->decode($session);
}
// Unserialize the session array
@@ -659,20 +671,20 @@ class CI_Session {
else
{
// if encryption is not used, we provide an md5 hash to prevent userside tampering
- $cookie_data = $cookie_data.md5($cookie_data.$this->encryption_key);
+ $cookie_data .= hash_hmac('sha1', $cookie_data, $this->encryption_key);
}
$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
// Set the cookie
setcookie(
- $this->sess_cookie_name,
- $cookie_data,
- $expire,
- $this->cookie_path,
- $this->cookie_domain,
- $this->cookie_secure
- );
+ $this->sess_cookie_name,
+ $cookie_data,
+ $expire,
+ $this->cookie_path,
+ $this->cookie_domain,
+ $this->cookie_secure
+ );
}
// --------------------------------------------------------------------