A few days ago a I noticed an interesting behavior in the session_regenerate_id() function. When it renames the session id it does not remove the old session, leaving it active and potentially usable by a would be hacker. This does not pose a problem if the function is only used during new session create as the means of preventing session fixation, which is the intended use btw. However, it makes it completely useless if used on each session based request to prevent session leakage via HTTP_REFERER and similar, since the previous session id is still usable. It also means that changing the id on “actions” as some scripts to do prevent session theft also is pointless; in fact it doubles the amount of session ids for the same user making it only simpler to assume their identity. Furthermore it means that on every call to the function there is duplication in the number of sessions entries that will hang around until they are considered expired and removed by the garbage collection process.
For this reasons, I have added an optional parameter to session_regenerate_id() in PHP 5.1, if set to true, it will force the session extension to remove the old session on an id change.
I have always recommended that the session identifier be regenerated when the privilege level changes (e.g., when a user logs in or something). If people follow this practice, then it will cause fewer problems.
The user can still go back to a page from before they were logged in, and links from that page will have an expired session identifier, but this seems fine. I think it will make sense to users that they have effectively gone back in time to a point before they were logged in (even if that's not exactly what is happening). It's like this imaginary threshhold.
There are still some auditing issues here, suppose you need to track currently browsing users on the site. If you use session_regenerate_id(), then when a user log in, or changes privelege level they now have a dual identity. This means that for tracking purposes you now have 2 active users, while in reality there is just one.
great, something i (and i guess many others, too) waited for a long time. i never understood this behaviour of leaving "old" sessions alive on the system (only reason i ever could imagine was exaclty this "back-button-break" Ilia described in his answer to chris. Anyway, thanks for this!
Thanks for this page. I am writing some code where the user changes privilege levels (as mentioned above) and i regenerate the session id. however, the user will be using the old session id simultaneously from another browser window to continue to do less privileged things. So, as long as leaving the old session intact is atleast an option, it will be great.
It's about time someone modified this horribly written function. I was so annoyed at it and the idiot, derick@..., basically saying I'm stupid and this how this function is "supposed" to work that I hacked session.c myself (PHP bug: http://bugs.php.net/bug.php?id=32631) and compiled php with the hack to have this behavior as default. It's good that you left compatibility using url-only sessions for people who think that's a better solution. Personally I think cookies are much more secure.