From: http://drupal.org/node/723802 #147
mfb writes:
Something I noticed while debugging another issue, and seeing various formats of session ids: If a user doesn't already have a session when they log in, the session id they are assigned is the "less random" one that is pre-generated for anonymous users. You can test this by appending some text onto the session id:
// Less random sessions (which are much faster to generate) are used for // anonymous users than are generated in drupal_session_regenerate() when // a user becomes authenticated. session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE)) . '-anon');
If an anonymous user already has an active session, then when logging in, her session will be regenerated via session_regenerate_id(), which allows us to use various PHP settings for improved randomness: session.entropy_file, session.entropy_length, session.hash_function.
Personally, I'd prefer to always have PHP generate highly random session ids using my hardened PHP session settings when users login.
If we leave the session id logic as is, at least the code comment should be clear about the fact that this "less random" session id will often be used for authenticated users.
It seems to me that this is a significant security issue. Now that session generation is always lazy (and hence should be rare) it seems to me that the easiest fix here is to always generate strong session IDs, regardless of anon vs. authenticated.
Comment | File | Size | Author |
---|---|---|---|
#21 | session-regen.patch | 1.49 KB | marcingy |
#12 | session-regenerate.patch | 1.55 KB | mfb |
#10 | session-regenerate.patch | 2.31 KB | mfb |
#9 | session-regenerate.patch | 2.24 KB | mfb |
#3 | session-regenerate.patch | 1.2 KB | mfb |
Comments
Comment #1
mfbThis session id issue has been around for a while, #723802: convert to sha-256 and hmac from md5 and sha1 just added some unclear/misleading documentation about it.
Over here (that issue was apparently caused by corruption of my sessions table although I did find some interesting things while debugging) I proposed always calling session_regenerate_id() when drupal_session_regenerate() is called (moving it down below the conditional if statement).
The only problem with doing this is that then there will be two session cookie headers, one when drupal_session_start() is called and one when session_regenerate_id() is called.
The header will look like this:
I believe that clients can handle this, by only using the second value of the cookie. But we may want to find a solution that gives us prettier headers..
Comment #2
mfbHere's the proposed fix described in #1, to always regenerate the session id via session_regenerate_id(), whether or not a session has already been started. Also added some comments re: the related PHP configs that can be used to "harden" session id generation.
Comment #3
mfbThis is an alternate fix which avoids the double set-cookie header (which I think is just an "aesthetic" problem, though there could be some client out there that can't handle it). It uses two totally different methods to generate the session id for the authenticated user, depending on whether or not an anonymous session had already been started.
Comment #4
Damien Tournoud CreditAttribution: Damien Tournoud commentedInstead of calling session_regenerate_id(), why not simply always generate our own session_id()?
Comment #5
Owen Barton CreditAttribution: Owen Barton commentedComment #6
mfb#2: session-regenerate.patch queued for re-testing.
Comment #7
pwolanin CreditAttribution: pwolanin commentedThe "weaker" one is what Drupal 6 uses for all users, so this issue is not as serious as it sounds.
I need to look at this patch with more context - for performance reasons we really don't want to be calling drupal_random_bytes() for every anonymous user who needs a session, but only calling it when a user logs in.
Comment #8
mfb@pwolanin I don't think that's correct: In Drupal 6, the session ids are always generated by PHP, not by Drupal, using whatever the PHP configuration is for session.entropy_file, session.hash_function etc. The "weaker"/"less random" session ids in Drupal 7 are generated by Drupal, not by PHP.
Comment #9
mfbHere's yet another alternative fix, as per #4 (DamZ):
With this patch, the PHP session id configs mentioned above have no effect; the session id is always generated by Drupal, using drupal_random_bytes() in drupal_session_regenerate() but not in drupal_session_initialize().
Comment #10
mfbFixed a typo in #9.
Comment #12
mfbAnother attempt for #9
Comment #13
pwolanin CreditAttribution: pwolanin commented@mfb - I must be thinking of the earlier version of Drupal 7 - before I added the code to use drupal_random_bytes()
Patch looks reasonable - we should never be using the session_regenerate_id() function any more I think.
Comment #14
bleen CreditAttribution: bleen commented@pwolanin: we still use session_regenerate in user.module in a couple places
Comment #15
pwolanin CreditAttribution: pwolanin commented@bleen - where? I don't see them
Comment #16
bleen CreditAttribution: bleen commentedoops .. I was misreading "drupal_session_regenerate();" as "session_regenerate();"
Comment #17
YesCT CreditAttribution: YesCT commented#12: session-regenerate.patch queued for re-testing.
Comment #18
YesCT CreditAttribution: YesCT commentedis pwolanin in #13 enough for rtbc?
Comment #19
YesCT CreditAttribution: YesCT commented#12: session-regenerate.patch queued for re-testing.
Comment #21
marcingy CreditAttribution: marcingy commentedJust a reroll of patch in #12.
Comment #22
catchI double-checked core and we're not using session_regenerate_id() anywhere once this lands. (While grepping I noticed that memcache-session.inc has similar code to here, so we should open a followup for that and any other pluggable session handlers when this lands).
Comment #23
pwolanin CreditAttribution: pwolanin commentedSomething about this patch doesn't seem right - seems to leave us with duplicate code.
Comment #24
pwolanin CreditAttribution: pwolanin commentedNever mind the above - there wasn't enough context in the patch to fully see what's going on.
Looking at the full function I think this the logic is correct. I was going to suggest forcing httponly as TRUE for the cookies, but I see with the way we use ini_set() we allow this to be changed from settings.php, which I guess may be needed in some rare cases.
Comment #25
marcingy CreditAttribution: marcingy commented#21: session-regen.patch queued for re-testing.
Comment #26
pwolanin CreditAttribution: pwolanin commentedCVS log says Dries committed it.
Comment #27
Gábor HojtsyThis patch made it impossible to log in with default PHP setups: #846330: Impossible to log in with default PHP settings due to cookie lifetime.