Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1

138 | Chapter 5: Security


The traditional session storage methods in Rails are server-side; they store all of the
session data on the server, generate a random key, and use that as the session ID.
The session ID is not tied to the data other than as an index, so it is safe to present to
the client without compromising confidentiality.


Rails uses as much randomness as possible to create the session ID: it takes an MD5
hash of the current time, a random number, the process ID, and a constant. This is
important: guessable session IDs allowsession hijacking. In a session hijacking
attack, an attacker sniffs or guesses a session ID from an authenticated user and pre-
sents it to the server as his own, thus assuming the authenticated user’s session. This
is similar to the TC Psequence-number prediction attack, and the mitigation is the
same: make the session IDs as random as possible.


Cookie-based sessions


There are many problems with server-side session storage. File-based storage, which
marshals the sessions to a local file on the server, is not scalable: to make it work in a
cluster, you either need a shared filesystem or a load balancer that supportssticky
sessions(directing all requests in the same session to one server in the cluster). This
can get tricky and is often inefficient. Database-backed sessions solve this problem
by keeping session state in a central database. However, this database can become a
bottleneck because it must be accessed once for every request that needs session data
(such as for user authentication). The DRb session store is not widely used and
requires running yet another server process.


There is a solution to these problems. Most Rails sessions are lightweight: they usu-
ally contain little more than a user ID (if authenticated) and possibly a flash mes-
sage. This means that they can be stored on the client rather than the server. The
Rails CookieStore does just this: instead of storing the session on the server and stor-
ing its ID on the client in a cookie, it stores the entire session in a cookie.


Of course, security must be taken into account. Remember the all-important rule:
never trust the client. If we just marshaled data into a string and placed it in a cookie,
we would have no way to prevent the client from tampering with the session. The
user could simply send the cookie corresponding to the session datauser_id=1and
trick the server into thinking that he was logged in as the user with ID 1.


To counter this, the CookieStore signs each cookie with an HMAC (keyed-hash mes-
sage authentication code), which is essentially a hash of the cookie data along with a
secret key. The client cannot forge or modify sessions because he cannot generate
valid signatures across the modified data. The server checks the hash on each request
and raises aTamperedWithCookieexception if the hash does not match the data. This is
the standard way to store data with an untrusted client while still assuring integrity.


In Rails 2.0, the CookieStore is now the default session store. The CookieStore
requires a secret key or phrase and session cookie key to be defined; it will raise an

Free download pdf