diff options
author | Andrey Andreev <narf@devilix.net> | 2014-05-31 20:00:05 +0200 |
---|---|---|
committer | Andrey Andreev <narf@devilix.net> | 2014-05-31 20:00:05 +0200 |
commit | 916b176594bcf175417423f33711ac0cbb4082e7 (patch) | |
tree | ba8e1fe4e8457005b1ca8635e7459159fea856e7 /system/libraries | |
parent | b4c693c50f54ecce1d0e2c1f203312f4bbb4af22 (diff) |
Backport HMAC authentication for CI_Session
Diffstat (limited to 'system/libraries')
-rw-r--r-- | system/libraries/Session.php | 56 |
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 + ); } // -------------------------------------------------------------------- |