Protecting Your Users Against Session Fixation

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

Prevalence Rare
Exploitability Moderate
Impact Harmful

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

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.

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.)

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>

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.

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
})

Sessions are tracked with cookies in PHP. Force generation of a new session ID using session_regenerate_id(true).

Further Reading

Ruby on Rails Security Guide.

ASP.NET Session State Overview.

Sessions in Java.