# Security problems with CookieStore and CSRF protection

**URL:** <https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460>\
**Category:** Rails\
**Created:** [October 18, 2009, 12:53am UTC](https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460 "2009-10-18T00:53:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Avik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f1d935/32.png) [@Avik](https://www.ruby-forum.com/u/Avik)\
**Post date:** [October 18, 2009, 12:53am UTC](https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460/1 "2009-10-18T00:53:57Z")

</div>

Dear Rails community,  
As part of a programming languages/security research group at the  
University of Maryland, we are building some static analysis tools for  
Rails applications. These tools work by taking formally specified  
properties of interest, and then analyzing code to verify that those  
properties indeed hold. Using these tools, we found some security  
vulnerabilities in Rails, and we would like to get a sense of how  
important these are in practice.

1. Using CookieStore opens the door to “replay attacks”, whose  
importance is, we feel, underestimated. A dishonest user can replay an  
old session to fool the server, of course; but more critically, it may  
be possible for an attacker to steal a cookie from an honest user  
after the latter is authenticated, and replay that session. The  
obvious fix is to include nonce-checking for every session object to  
ensure its freshness, but this may require storing nonces in the  
database, which may go against the point of using CookieStore. Are  
most users of Rails aware of this problem? How many actually use  
ActiveRecordStore instead of CookieStore? If the latter is by far the  
most common mode, then we believe that default should be  
ActiveRecordStore, as it is much less susceptible to this problem.  
(Session ids are usually not stateful in a bad way.)

2. The CSRF protection, at least in Rails 2.2.2, seems too weak. Rails  
comes close to implementing a fix, by embedding and checking hidden  
tokens (for POST requests). But it is well-known that for such a fix  
to work, the tokens should be session-specific. Unfortunately, we  
found that the implementation in 2.2.2 can return the same token even  
if, e.g., session[:user] is different. This is bad, since an attacker  
may not be an outsider: it can reasonably have an account with the  
server, and if it gets back a token which it can then embed in forms  
used by other, honest users, then it can execute CSRF attacks!

The common theme behind these attacks is that it may be too simplistic  
to view the world as divided between a (trusted) server and an  
(untrusted) attacker. Users should be isolated from other users just  
as well, be it for protection against CSRF, or protection against  
session replay.

Do you, as users and developers of Rails, think these are issues  
important enough to worry about? We would like to hear any counter-  
arguments.

Best regards,  
Avik Chaudhuri.  
[[Avik Chaudhuri @ Facebook](http://www.cs.umd.edu/~avik)]

---

<div class="post-metadata">

**Author:** ![Avik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f1d935/32.png) [@Avik](https://www.ruby-forum.com/u/Avik)\
**Post date:** [October 18, 2009, 1:03am UTC](https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460/2 "2009-10-18T01:03:54Z")

</div>

On Oct 17, 9:14 pm, Avik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> most common mode, then we believe that default should be  
> ActiveRecordStore, as it is much less susceptible to this problem.  
> (Session ids are usually not stateful in a bad way.)

All true, but I’ve always thought that at the point where people can  
steal your cookies then you’re a bit shafted anyway. The replayability  
does make it a bit worse than just stealing a session cookie, but then  
a lot of sites have a ‘remember me’ cookie, why bother stealing the  
session when you could steal that ?

> 1. The CSRF protection, at least in Rails 2.2.2, seems too weak. Rails  
> comes close to implementing a fix, by embedding and checking hidden  
> tokens (for POST requests). But it is well-known that for such a fix  
> to work, the tokens should be session-specific. Unfortunately, we  
> found that the implementation in 2.2.2 can return the same token even  
> if, e.g., session[:user] is different. This is bad, since an attacker  
> may not be an outsider: it can reasonably have an account with the  
> server, and if it gets back a token which it can then embed in forms  
> used by other, honest users, then it can execute CSRF attacks!

That’s seems odd - glancing at the code it would seem that in 2.2.2  
the secret is a digest of the session\_id and a secret (for non cookie  
stores) and in the case of a cookie store a digest of a random  
identifier and a secret. How were you able to get it to return the  
same token for 2 different sessions ?

Fred

---

<div class="post-metadata">

**Author:** ![Avik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f1d935/32.png) [@Avik](https://www.ruby-forum.com/u/Avik)\
**Post date:** [October 19, 2009, 4:19pm UTC](https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460/3 "2009-10-19T16:19:15Z")

</div>

Hi Fred,

> That’s seems odd - glancing at the code it would seem that in 2.2.2  
> the secret is a digest of the session\_id and a secret (for non cookie  
> stores) and in the case of a cookie store a digest of a random  
> identifier and a secret. How were you able to get it to return the  
> same token for 2 different sessions ?

According to the code for 2.2.2 (and also the current version), the  
token is not inherently “user-specific”; it may remain the same even  
when other session fields change. Thus, the app _must_ use  
reset\_session when a different user logs in to force a different token  
to be computed. (In particular, just clearing out the relevant fields,  
e.g., session[:user\_id], is not enough, since session[:\_csrf\_token] or  
session[:csrf\_id] remains set.) Otherwise, we may get the following  
scenario, for example.

1. Attacker logs into a public computer, gets CSRF token from a page  
returned by the server, includes a form with that token on a popular  
website he controls, and leaves without logging out.

2. Honest user logs into the same computer (and say reset\_session is  
not used, so the token field in the session remains set and doesn’t  
change). He opens the popular site on the side, and accidentally  
causes the malicious form to be sent.

I discussed this issue with Michael K.; he claims, perhaps  
rightly so, that this is ultimately a session fixation attack, and the  
doc already advises use of reset\_session in that case. True, but I  
believe that the doc is inadequate in this case; clearly this attack  
uses CSRF, and the fact that protection in this case requires  
protect\_from\_forgery as well as reset\_session is not clarified enough.

Best,  
-Avik.

---

<div class="post-metadata">

**Author:** ![Avik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f1d935/32.png) [@Avik](https://www.ruby-forum.com/u/Avik)\
**Post date:** [October 19, 2009, 4:48pm UTC](https://www.ruby-forum.com/t/security-problems-with-cookiestore-and-csrf-protection/177460/4 "2009-10-19T16:48:31Z")

</div>

On Oct 19, 3:17 pm, Avik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> According to the code for 2.2.2 (and also the current version), the  
> token is not inherently “user-specific”; it may remain the same even  
> when other session fields change. Thus, the app _must_ use  
> reset\_session when a different user logs in to force a different token  
> to be computed. (In particular, just clearing out the relevant fields,  
> e.g., session[:user\_id], is not enough, since session[:\_csrf\_token] or  
> session[:csrf\_id] remains set.) Otherwise, we may get the following  
> scenario, for example.

Ah, with you know - thought you were saying that two completely  
unrelated sessions might end up with the same auth token.

Fred
