Security::cipher() problems and Suhosin
Over a week ago I migrated one of my sites to a MediaTemple (ve) Server. I installed nginx, PHP 5.3.2 (with Suhosin), MySQL, APC and Memcache. After a little configuration and debugging, everything was working smoothly except encrypted cookies. I was using my AutoLogin component and login never persisted, but regular cookies worked correctly. I thought it would be an easy fix but I was wrong (I will post another blog on this topic).
While trying to figure out the encryption problem, I debugged the CookieComponent. I tested each function individually around a fake array. I tested __implode(), __encrypt(), __explode() and Security::cipher(). My results were all over the place. When I tested the script locally, everything worked correctly and the ciphering process worked as it should (below). But on the live server, all the encryption strings would change each refresh and the un-cipher would never work.
Implode:
username|gearvOsh,password|dsadnas79dn7n1279dnadnadb1p2sdasd,hash|761c1168c645784b78f5f967160ab390,time|1286152916
Ciphered:
z~¡|ßÛí�"� =�'¥¾E¨ÿÏy� íåÇv¸”^ëS ¦ì•ˆxuŽ?��ãbm}ÜfÇ“„bËV´w±(ÃU�"éQ’Qñn²^6¿2r‰½ùé‹ÄáÄ,‡ ›d¤<ó`'ëÆìÏg$V")ËdÁ&µ‰
Base64 encode:
Q2FrZQ==.en6hfN/b7dMfij3Spb4ERaj/z3ng7eXHdriUXutTIKbslYh4dR6OP8bjYm193GbHk4Riy1a0d7Eowx+QVZbpUZJR8W6yXja/MnKJvfnpixsIxOHELIcgm2QHpDzzYCfrxhrsz2ckVggijwcpy2TBJrWJ
Using Cookie::__encrypt():
Q2FrZQ==.en6hfN/b7dMfij3Spb4ERaj/z3ng7eXHdriUXutTIKbslYh4dR6OP8bjYm193GbHk4Riy1a0d7Eowx+QVZbpUZJR8W6yXja/MnKJvfnpixsIxOHELIcgm2QHpDzzYCfrxhrsz2ckVggijwcpy2TBJrWJ
Base64 decode:
z~¡|ßÛí�"� =�'¥¾E¨ÿÏy� íåÇv¸”^ëS ¦ì•ˆxuŽ?Æãbm}ÜfÇ“„bËV´w±(ÃU�"éQ’Qñn²^6¿2r‰½ùé‹ÄáÄ,‡ ›d¤<ó`'ëÆìÏg$V")ËdÁ&µ‰
De-ciphered:
username|gearvOsh,password|dsadnas79dn7n1279dnadnadb1p2sdasd,hash|761c1168c645784b78f5f967160ab390,time|1286152916
As you can see from the debug (on my local machine), the beginning and resulting strings are the same. I then found out the problem was with Security::cipher() and srand(). I later found out that Suhosin was overriding the srand() and mt_srand() functions, which was causing my seed to always change. I tried disabling Suhosins overwrites, but to no avail.
// Did not work
ini_set('suhosin.mt_srand.ignore', 0);
ini_set('suhosin.srand.ignore', 0);
After some googling and a lot of frustration, I finally found a solution. Thanks to Edgar Valarezo, I was able to get my encrypted cookies working properly. However, I had to overwrite CakePHP's core Security class and will need to maintain it every time I upgrade Cake. Here is the new cipher() snippet for your convenience.
function cipher($text, $key = '') {
$key .= Configure::read('Security.cipherSeed');
$out = '';
$textLength = strlen($text);
$keyLength = strlen($key);
$k = 0;
for ($i = 0; $i < $textLength; $i++) {
$seed = md5($key . $key[($k++) % $keyLength]);
$mask = hexdec($seed[6] . $seed[9]); // :)
$out .= chr(ord($text[$i]) ^ $mask);
}
return $out;
}
I see this as a temporary fix and would love any information on this topic. If you ran into this same problem, how did you correct? Is it possible to seed correctly with Suhosin? Thanks again!
6 Comments
But on my Linux Server it throws "Cookie names cannot contain any of the following '=,; \t\r\n\013\014' in [/srv/www/.../Cake/Controller/Component/CookieComponent.php, line 412]"
Not sure if it is related to the above Suhosin problems. But I don't think so as it seems to have something to do with incorrect chars.
i love this component, good job !
I was facing the same problem with cookie encryption, I have Suhosin installed.
In my case it was solved by putting in my php.ini
suhosin.srand.ignore = Off
It is working now without any issues...
I had this problem too, and I change something with keys, I had all the time this error: You cannot use an empty key for Security::cipher()
I forgot what i did with that.
I have another problem when using it with auth, when user session is out, you make hit on the page, and then you have been logged in again and redirected not on page that you make hit, already on default after login page. And same process login it again takes to long.
Any idea how to solve this?
Tnx, btw. great component. I like it.
If you're not maintaining a separate fork of the CakePHP core itself, I'd think this would be easier for maintainability.
I arrived here trying to find out why the AutoLogin component was behaving strangely with encrypted cookies. And yes, I have Suhosin installed...
So, first of all thank you for your testing, most likely I would not be able to find such a subtle problem.
I'll keep you updated if something useful arise, please do the same.
Best, Mario