UPDATE: This issue has received press coverage and made it into the Open Sourced Vulnerability Database (OSVDB) available at http://osvdb.org/show/osvdb/97726. I will follow up on this post with more technical details as well as my research results from studying this issue in the wild.
Ruby on Rails Web applications versions 2.0 through 4.0 are by default vulnerable to an oft-overlooked Web application security issue: Session cookies are valid for life.* The fix is to configure your Rails app to store most session information on the server side in the database.
Background
The default Rails session storage mechanism is the CookieStore, which holds the entire user session hash on the client side in the Web browser as a cookie. In this configuration there is no entry in a “sessions” database table for your Rails app to delete upon logout.
My concern is more than just current session hijacking via Firesheep or similar; a malicious user could use the stolen cookie from any authenticated request by the user to log in as them at any point in the future.
When a user logs out what happens is not what you would expect. Again, no entry in a “sessions” table exists to delete. Instead, Rails will issue a new, empty-ish cookie to the user’s browser in order to overwrite the one granted when the user originally authenticated, and instruct the Web browser to use this newest one from this point forth. This relies on good browser behavior. But remember, the previous cookie is still valid. There is no way to invalidate these old cookies upon sign out with the default Rails configuration. In addition to network snooping (session sidejacking) and XSS, this presents a problem for users accessing your site via a shared or public computer, or perhaps over a faulty network connection that might drop the very last HTTP response requesting that the user’s browser overwrite the stored authenticated cookie. Also, when your users forget to logout, they will not be able to log themselves out of that living session from a different computer, and anyone who discovers the stored cookie can use it indefinitely.
The default cookie name is:
“your_app_session”
And before Base64 encoding and URL encoding, the cookie value may look something like this with actual values for “[String]”:
{ I"session_id:EF"%[String]I"_csrf_token;FI"1[String]=;FI"user_credentials;FI"[String];TI"user_credentials_id;Fi
While Rails 4 switched to encrypting the value of the cookie, doing so does not eliminate this issue.
Separately, it is a good design for your Web app to require that the user supply their current password before changing sensitive fields such as password or email address. If the CookieStore-stored session were to be hijacked, the malicious user could change the user’s password: 1) immediately invalidating the legitimate user’s cookie and thus slamming your app’s doors in their face and 2) disallowing the legitimate user the ability to log back into their account.
A note about a red herring: if you use the Authlogic gem you may notice a field called “persistence_token” in your users table and believe that you are already using server-side storage for most of your session data. In my testing of the default CookieStore configuration, the field did not appear to serve a purpose.
Remediation
Switch to ActiveRecordStore or something else from this list. Switching away from CookieStore is said to be slower. After switching, the cookie will contain a value for “session_id” which corresponds to an entry in your database’s sessions table. You will need to keep in mind replicating session data across multiple databases if you have more than one active behind a load balancer.
Happy hacking! Email me with questions: Main@GSMcNamara.com
*In my testing, the only methods to invalidate these cookies are for the user to change their password or for systems administrators to change the application secret. Both are infrequent occurrences.
@GSMcNamara caught a link off twitter a day before it hit F-D, crazy vuln and a good find
— OSVDB (@OSVDB) September 27, 2013
#Security Issue in Ruby on Rails Could Expose Cookies – http://t.co/OkSfrAbAeF
— Threatpost (@threatpost) September 25, 2013
Hear about a big Ruby on Rails #vuln first publicized by @GSMcNamara http://t.co/ac3SG7FzXe
— WhiteHat Security (@whitehatsec) September 27, 2013
Good to know! I looked it up, looks like this developer realized a while ago that replay vulnerabilities were a problem:
http://shivampatel.net/blog/index.php/2011/07/18/replay-attacks-on-rails-applications-using-cookie-store-for-session-management/
Thanks for posting this technical article! It was a joy to read.
It should be noted that after hijacking a session or resuming a one thought to be dead by the real user, a change by the malicious user of any of those session variables would immediately invalidate the stored cookie on the real user’s machine, and then they would be locked out of the app. They might also then not be able to re-authenticate, if the hijacker were able to set fields used to authenticate, such as username, password, or email address.
Pingback: Some Versions of Ruby on Rails Could Expose Cookies | Threatpost
Pingback: Security Issue in Ruby on Rails Could Expose Cookies « Cyber Security Aid
Pingback: Vulnerability in Ruby on Rails 2.0 – 4.0 Allows Hackers to Hijack Accounts | Cyber Security Infotech(P) Ltd
Pingback: Security News #0×54 | CyberOperations
Pingback: Security Vulnerability with Django Cookie-Based Sessions | MaverickBlogging
Pingback: Logout is broken by default in Rails | Boardmad
Pingback: CookieStore vulnerability in Rails 2.x, 3.x, 4.x. | Rocketboom
Pingback: CookieStore vulnerability in Rails 2.x, 3.x, 4.x. | Enjoying The Moment
Pingback: How bad is rails’ cookie system? |
Pingback: Episode 112 – Facebook CSRF, KnockoutJS 3 | WebDevRadio
Pingback: Episode 112 – Facebook CSRF, KnockoutJS 3 | PHP Podcasts
Pingback: Ruby on Rails ใช้ CookieStore เป็นมาตรฐาน หลายบริการสามารถใช้ cookie เดิมล็อกอินซ้ำได้ | PantipGuide.com
Pingback: Ruby on Rails ใช้ CookieStore เป็นมาตรฐาน หลายบริการสามารถใช้ cookie เดิมล็อกอินซ้ำได้ | Webtheboy.com เว็บไซต์วาไรตี้
Pingback: Ruby on Rails ใช้ CookieStore เป็นมาตรฐาน หลายบริการสามารถใช้ cookie เดิมล็อกอินซ้ำได้ | ละครย้อนหลัง,ข่าว,คลิปว
Pingback: Ruby on Rails ใช้ CookieStore เป็นมาตรฐาน หลายบริการสามารถใช้ cookie เดิมล็อกอินซ้ำได้ | ข่าวไอที
Pingback: Improving Rails Security with CacheStore | Second Forge
Pingback: Top 10 Web Hacking Techniques 2013 | My reading
Pingback: Top 10 Web Hacking Techniques 2013 | WhiteHat Security Blog
Pingback: Logging Out of a Rails App That Uses session_store = :cookie_store | Alaina Hardie