2

I have a Rails app that stores session information in a database, and user information in an "users" table with "id" as primary key with auto increment on.

Upon login users can go to a "products" page where it shows their products filtered by ID:

@products = Rails.cache.fetch("user-products-" + session[:id].to_s, {:expires_in => 30.minutes}) do
Product.where(:user_id => session[:id])
end

Something really baffling is happening: sometimes users can see other users' products, apparently at random. I have checked the user IDs in the products table some 10 times already, it makes no sense at all. Same happens with other things I store into memcache, such as for example user first and last names, addresses, settings...

This happens at random, it's not consistent. Possibly when there's a lot of traffic (users reported this happening at peak hours).

In my config/application.rb:

config.cache_store = :dalli_store, "memcached.mydomain.com", { :namespace => "Frontend", :pool_size => 10 }

In config/initializers/session_store.rb

Rails.application.config.session_store :active_record_store, key: '_ssbl_session', :expire_after => 7.days

I use Ruby 2.3.1, Rails 4.2.5, the Dalli gem v 2.7.6 with connection_pool 2.2.1 and activerecord-session_store 0.1.2, Apache 2.4.6, Passenger 5.0.26, memcached 1.4.15 on CentOS 7.

Things I have tried:

  1. initially I was using the other memcache store gem, problem was still there, changed to Dalli, problem still here (is this trying to tell me it's not something related to Rails or any of the gems?);
  2. different session expiration - tried 1 to 15 days;
  3. clearing memcache data;
  4. clearing sessions table;
  5. changing the namespace;
  6. I also just started pinning session IP (to force a logout when a last_ip stored in memcache is different than current IP), I guess I will see how this goes...but the problem will still remain even if users will get logged out instead of seeing other users' purchases, they will whine about getting kicked out instead...2 weeks later however this is still happening, without the user getting kicked out. It's like some parts of the session get overwritten by data from other sessions.
  7. I also realized something else: my sessions table would end up having something like 40K records due to the length of the session (7-15 days, what can I say, UX improvement...), but unfortunately I wasn't inspired enough to check for duplicates, if it's even possible to have a md5 collision within 40K hashes...
  8. I also started logging every hit into a table where I include the session_id, user.id and IP address... will see if this data is useful or not.

I have already checked answers like: Users take sessions of other users when sessions are stored in memcached (Rails) . I get a 500 when adding that code.

Any help would be appreciated.

Later edit:

I set the session[:id] after users log in:

def process_login
   ...
   # at this point I have authenticated the user by e-mail and pwd and have the object in the "user" var
   session[:id] = user.id
   ...
end

Edit 10 March: I am no longer storing any session data into memcache. I have removed the "dalli" and "memcache" tags from the question. The issue persists. I was still not able to reproduce this however I can see it is real because logs for sessions affected by this issue contain hits to controllers they would not be able to access.

Community
  • 1
  • 1
Nick M
  • 2,424
  • 5
  • 34
  • 57
  • May you also show how do you assign `:id` to `session` object? Maybe problem is in that piece of code – Slava.K Jan 31 '17 at 08:36
  • Yeah I see what you mean... I'm also thinking to investigate any effect Cloudflare might have on session cookies (I have CF in front of the sites) – Nick M Jan 31 '17 at 08:52
  • yeah, cloudflare... Have you heard about recent crisis? :) – Sergio Tulentsev Mar 10 '17 at 12:45
  • Yes... and I am not sure this could be the cause since it's still happening, and also my application kicks out users who attempt to access a product which does not belong to them. So even if an user sees someone else's products (due to the cloudbleed bug), they would not be able to interact with it because they would get kicked out. The fact that they are able to interact with foreign products means that the entire session overlaps with another that has privileges on these products (such as for instance my admin session that has privileges over all products, or any other user that purchased). – Nick M Mar 10 '17 at 13:11

0 Answers0