Session fixation in Rails

These attacks focus on fixing a user's session identifier known to the attacker, and forcing the user's browser and the web application into using this identifier. The first step in such attacks is to create a valid session identifier. While other session managements (in PHP, for example) accept arbitrary identifiers, and create a valid session with the session identifier if it does not exist yet, this is not possible in Ruby on Rails.Rails accepts only session identifiers which have been generated by itself, and will issue a new one if you propose an arbitrary one. So with Rails applications, an attacker has to access the site of web application in order to obtain a valid session identifier.

The next step is to force a victim's web browser into using this identifier, which is know as the actual session fixation. According to RFC2965, a website cannot set a cookie for another domain. So the attacker cannot set a cookie for the web application by luring him on a site that he controls. One possibility to fixate the session, which requires the ability to sniff and modify data traffic between the user and the web application, is to change the session identifier in a response from the server. Or, if he has access to the user's DNS-server, he can redirect requests to a server taken over by the attacker, which forwards and modifies request to and from the original web server. The next two possibilities to fixate the session have to do with User Agent Injection (also: XSS) vulnerabilities. The first approach to do this is to change the cookie by setting document.cookie to a desired value, for example in JavaScript:

 

document.cookie='_session_id=16d5b78abb28e3d6206b60f22a03c8d9';

However, a web application administrator might know this vulnerability, and therefore has an appropriate flter for that. A less known approach is to set the cookie with an injected <META> HTML tag. Normally, <META> tags belong between the <HEAD> tags at the beginning of the document, however, it will be processed by the browser anywhere in the document. Inject this line, for example:

<meta http-equiv=Set-Cookie content="_session_id=
4cf69dc5fee46251bdc1f99ef55f52b6">

After the session identifier has been successfully injected into the user's browser and he logged in to the trap session, the attacker will be able to use the session, until the user logs out.

A good countermeasure against creating a valid session identifier is to not to issue them on pages that everyone can access. That means, for example the login page, should not send a session identifier to the yet unauthorized user, do so only after the user has been authorized. With the following you can turn the use of sessions in a specific controller off:

 

session :off # turn it off for any action
# or turn it off for any but these actions
session :off, :except => [ :change_password, :edit, :delete ]

However, you have to bear in mind that a request to any URL which issues a session identifier to logged in users also issues it to unauthorized users, but redirects then. And if the application is open to everyone, i.e. you can sign up on your own, you cannot prevent an attacker from signing up and retrieving a valid session identifier.

One of the most effective countermeasures is to issue a new session identifier after a successful login. That way, an attacker cannot use the fixed session identifier. By the way,this is also a good countermeasure against session hijacking. The following lines create a new session in Rails:
 

reset_session