, and a very inciteful node about maintaining state from a while back, that I can’t seem to find (talked about SSL, javascript MD5, PGP etc.), as well as reading various other articles, books, and examining the internals of Apache::Session I would seek the wisdom of monks on the ultimate Sessions management system!
The system I have proposed to myself, and undertaken the creation of is more complicated than Apache::Session for an array of reasons, mainly because I found Apache::Session to be interestingly inadequate for SSL, and in other specs as well.. Here is my implementation of sessions, and I would love to have monks of greater incite quizzing me on its’ insecurities, as well as implementation.
To begin with, the script is for mod_perl, in order to maximize speed, and limit the amount of connections to the cache necessary. Therefore I globalize a ‘CypherKey’, ‘CipherObject’, and a ‘HMAC Object’, so I do not have to reload the modules every execution. The script checks a user’s cookies, and retrieves a session hash, and a cache hash. If the script is not executed under SSL, the cache hash will return undef, as it is set with SSL => 1, by Apache::Cookie.
Returned from the cookie are a:
- Session hash (in all cases), containing two session keys, as well as a MAC.
- Cache hash (during SSL transactions.), containing a cache key, as well as a MAC.
I then open up a cache, as merlyn instructs us to do in the Web-Techniques column, except this caches is used a tad bid differently. It is used:
- For getting a cache value from the cache hashes key.
- For checking whether or not the cipher has been recently changed.
If a day has expired, it is time to generate a new ‘CypherKey’, ‘CipherObject’, and a ‘HMAC Object’, from MD5 hexhashes once again. They are then set into cache, for other mod_perl processes to take advantage of, if the cipher has not been recently changed, but if the process is new (using the ||= operator.) At this point, all the objects had better be available (the most important being the cipher.) I then decrypt the information created by the sessions hash with the cipher, and the decrypt hex function (values were encrypted by blowfish, in the first place.)
I check to see if the cache hash was defined, and make sure that the cache hashes MAC is still maintained, the $HKEY is used here, to check the MAC (The HKEY is the key in Digest::HMAC.) If the hash remains integral, we plug in the key from the cache hash into the cache to get a result.
We then do the same for sessions, except we use Apache::Session to get the result. Apache::Session has been modified to allow for two parameters, a session id, the first session hash parameter, and a session hash, the second parameter, which is a MD5 string. This ensures that the 1:Howmanypossibilities rate is ensured, instead of having the chance of hash hijacking increase.
Afterwards, I delete the cache, if Apache::Session did not return a session, as the session would have expired, (a very improbably case… but still… I do not reset cookies on most pages…) Otherwise I just renew the session in cache, and read the authorization type, and other pertinent Session information.
This system ensures:
- That the user has been logged in, within the last * hours, to do any critical work.
- That sniffing out even the cookies not always transmitted over SSL is useless, as the cookie will change, every day. (I may use an old_* field in cache, in order to set cookies to new values, if they were from the previous day.)
- That modifying cookies is close to impossible.
Any advice on how to make the system more secure? Any advice on implementing more precise, or cleaner features? This deals with specific authentication and now password retrieval, and that stuff, as the current system for those is perfectly fine. This may be overdoing it, but that’s what I’m trying to do, at this point ;) Of course this is extreme, but I'm trying to design something with as little a weakness as possible. Therefore I need your sugestions.
Gyan Kapur
gyan.kapur@rhhllp.com