From e2bceaefe6b4723230fd33a30e11c1c927712998 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sat, 18 Jul 2015 16:05:34 +0200 Subject: [PATCH] Support more secure hashing algorithms for auth cookie - configurable by PHP's session.hash_function (#1490403) --- .htaccess | 1 + CHANGELOG | 1 + program/lib/Roundcube/rcube_session.php | 57 +++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/.htaccess b/.htaccess index 95e5bf475..c584ac0fb 100644 --- a/.htaccess +++ b/.htaccess @@ -17,6 +17,7 @@ php_flag magic_quotes_runtime Off php_flag suhosin.session.encrypt Off #php_value session.cookie_path / +#php_value session.hash_function sha256 php_flag session.auto_start Off php_value session.gc_maxlifetime 21600 php_value session.gc_divisor 500 diff --git a/CHANGELOG b/CHANGELOG index 7847106d5..76153fe27 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Support more secure hashing algorithms for auth cookie - configurable by PHP's session.hash_function (#1490403) - Require Mbstring and OpenSSL extensions (#1490415) - Get rid of Mail_mimeDecode package dependency (#1490416) - Add --config and --type options to moduserprefs.sh script (#1490051) diff --git a/program/lib/Roundcube/rcube_session.php b/program/lib/Roundcube/rcube_session.php index 2d26ad6b7..86316f9d1 100644 --- a/program/lib/Roundcube/rcube_session.php +++ b/program/lib/Roundcube/rcube_session.php @@ -628,15 +628,66 @@ abstract class rcube_session } /** - * Create session cookie from session data + * Create session cookie from session data. + * The cookie will be hashed using a method defined by session.hash_function. * * @param int Time slot to use + * * @return string */ - function _mkcookie($timeslot) + protected function _mkcookie($timeslot) { $auth_string = "$this->key,$this->secret,$timeslot"; - return "S" . (function_exists('sha1') ? sha1($auth_string) : md5($auth_string)); + $hash_method = (string) ini_get('session.hash_function'); + $hash_nbits = (int) ini_get('session.hash_bits_per_character'); + + if (!$hash_method) { + $hash_method = 'md5'; + } + else if ($hash_method === '1') { + $hash_method = 'sha1'; + } + + if ($hash_nbits < 4 || $hash_nbits > 6) { + $hash_nbits = 4; + } + + // Hash the authentication string + $hash = openssl_digest($auth_string, $hash_method, true); + + // Above method returns "hexits". To be really compatible + // with session hashes generated by PHP core we'll get + // a raw (binary) hash and convert it to a readable form + // as in bin_to_readable() function in ext/session/session.c. + $hextab = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-"; + $length = strlen($hash); + $result = ''; + $char = 0; + $i = 0; + $have = 0; + $mask = (1 << $hash_nbits) - 1; + + while (true) { + if ($have < $hash_nbits) { + if ($i < $length) { + $char |= ord($hash[$i++]) << $have; + $have += 8; + } + else if (!$have) { + break; + } + else { + $have = $hash_nbits; + } + } + + // consume nbits + $result .= $hextab[$char & $mask]; + $char >>= $hash_nbits; + $have -= $hash_nbits; + } + + return $result; } /**