Session Fixation vulnerabilities can make your users liable to having their session hijacked. A secure implementation of sessions on your site is key to protecting your users.
Risks
Session hijacking allows hackers to bypass your authentication scheme with impunity. This is almost the worst thing that could happen, security-wise – and you may not know when it has occurred!
Protection
Don’t Pass Session IDs in GET/POST Variables
Passing session IDs in query strings, or in the body of POST requests, is problematic. Not only does it make crafting of malicious URLs possible, but session IDs can be leaked in the following ways:
- If the user follows an out-bound link (the
Referer
header will describe where the user browsed from). - In the browser history and in bookmarks.
- In logs on your web server, and any proxy servers.
Session IDs are better passed in HTTP cookies. See the code samples below for examples of how to do this.
Regenerate the Session ID at Authentication
Session fixation attacks can be defeated by simply regenerating the session ID when the user logs in.
Accept Only Server-Generated Session IDs
It is a good practice to ensure that only server-generated session IDs are accepted by your web server. (On its own, this won’t resolve session fixation vulnerabilities, though. A hacker can easily get a new server-generated ID and pass it onto a victim in a crafted URL.)
Timeout and Replace Old Session IDs
Periodically replace session IDs as a second layer of defense, should they get leaked.
Implement a Strong Logout Function
The logout function on your website should mark session IDs as obsolete. (You do have a logout function, right?)
Require a New Session When Visiting From Suspicious Referrers
Consider forcing your users to login again, if they visit your site from a separate website (e.g. web-mail).
Code Samples
Python
Django
Django tracks session IDs using cookies by default, though you will have
to enable sessions
in your settings file. Call
cycle_key()
to reset the session ID after login.
Ruby
Rails
A cookie-based session store is the Rails default, which affords you a great
deal of protection against session fixation. To make things fully secure, you
should reset the session ID by calling
reset_session
in your login process (typically this is implemented by a SessionsController#create
action.)
Java
Servlets/Java Server Pages
In a Java servlet container, you can configure sessions by modifying your
web.xml
. Best practice is to track session IDs using cookies. If possible, you
should also force your server to only track session IDs over HTTPS, and timeout
sessions after a period of inactivity.
To regenerate a session ID after authentication, call
HttpSession.invalidate()
,
then create a new session with
HttpServletRequest.getSession(true)
.
<session-config>
<tracking-mode>COOKIE</tracking-mode>
<session-timeout>15</session-timeout>
<cookie-config>
<secure>true</secure>
</cookie-config>
</session-config>
C#
ASP.NET
By default, ASP.NET tracks session IDs using cookies. Forcing the server to regenerate a session ID is not straightforward in .NET - consider using the NWebSec library to ensure secure treatment of session IDs.
Node
Express.js
Express tracks session IDs in cookies. Interestingly, you can supply your own session ID generation algorithm (the recommended approach is to use UUIDs). You can force generation of a new session ID with:
req.session.regenerate(function(err) {
// New session here
})
PHP
Sessions are tracked with cookies in PHP. Force generation of a new session ID using
session_regenerate_id(true)
.
Further Reading
ASP.NET Session State Overview.