-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lots of session collisions #25
Comments
The method should be sound - it's using 64 bits of an instance of SystemRandom(), which in turn should be using A UUID4 will be using pretty much the same sources of randomness. A UUID1 might prevent your issues in theory, but can only deliver around ~128 or so UUIDs per tick and machine as well. I'm confident that the basic idea is sound, here's what I think could be the problem: You have a lot of machines this runs on in parallel and they have little entropy (dedicated servers without hwrngs?) and the same startup state. That'd be hard to do, but somewhat conceivable - I think that's not likely. Most likely, there's an issue with the implementation either inside the library (my bad) or the surrounding app server. What does your application server look like? Does it fork per request? That + a bad system-random source would be the easiest way to generate duplicate session ids. I'll have a look at By the way, if you really want to use UUIDs, you can put it to the test: Write a function supporting the "getrandbits()" method that derives it from a generated UUID. It'd be nice if you could share some more info on your specific deployment though. |
From Python's random.py:
``getrandbits()` is just a wrapper for calling os.urandom(), as expected. Did you try increasing SESSION_KEY_BITS in your config to 128, or even 256? |
Actually, the more I think of it, the more likely it seems that its not a security problem - the same session is simply created twice on a storage level. I assume you're using simplekv's SQL database backend. When updating a session, it will be If that is the case you do not have as glaring a security problem (though I could think of others resulting from, so this is still worth fixing!) - only someone who knows the session id can cause the issue (to verify you could check if duplicate session problems originate from the same IPs as the ones where the user legitimately holds said session) and it will currently cause some information inside the session to be lost (i.e. not written when updaing the session). Those are my hunches for now, I need a little more information to work with to fix =). You can mail me, of course, if any of that stuff is confidential. |
In closing, I've checked on
A pragmatic short term solution for your deployment may be moving to a redis backend, which handles all these things much easier. Sorry that I can't help out more on short notice. You're very welcome to dig deep into the details of transactions and upserts across databases and fixing the issue by writing a better implementation for Some reading: |
@mbr Thanks so much for your reply. Really helps to illuminate what has been a puzzling and frustrating issue. The issue is actually pretty serious for us as even with a small set of concurrent users (around 40 as opposed to the upwards of 10K that we're expecting at launch) we're still seeing this happen with some frequency. Switching to Redis might be the best solution at this point as it will likely be faster and less fraught with problems. Perhaps adding a warning on this plugin as regards using it with pgSQL might be helpful? I'd be more than happy to contribute in any way that I can. |
I'll add some more info regarding our deployment to this post shortly. |
I also had collisions appearing with FileStorage. |
I'm not sure yet, but i think i've experienced it too using redis ... |
@macrojames, @eMerzh: Can you supply some debugging output? Possibly even a small test case? |
I have seen this error too, using memcached as backend. In my case I saw a memcache error (weird time-outs being one of three users on a testing env) after that I tried to login to my app and the data that was available was from another user. I also make use of session.regenerate() for security reasons. when I see it again (I've seen 3 or 4 times already) I will try to see if it is always related to an error in the persistance mechanism. |
I am grateful for any reproducible test case. Unfortunately, I have not run into the issue myself yet, which makes it hard to pin down and fix. |
Any more news on this @mbr @etscrivner ? @etscrivner what did you end up using for server-side session storage since you found this one unreliable? Sounds like changing your session backend to Redis or using Flask-Session instead is preferable |
I haven't followed up on this, as I am still without a reproducible problem =). @etscrivner Details would be appreciated. @mmautner Do you run into this issue as well? If so, could you maybe post some (minimal?) example code that reproduces the issue? |
@mbr Whoops my apologies, clicked the wrong button here. I was never able to fully fix this issue despite attempting all manner of solutions. My suspicion is that it's a deeper problem either with how we configured Flask with uwsgi or it with some non-threadlocal data getting stomped. There probably won't be a "minimal test case" except doing something like load-testing with JMeter and waiting for the error. That was the only way I was able to consistently reproduce. |
@mbr Anything new about this? I'm using flask's default client side session, but I'm also faceing a similar issue that some user logs into another's account with no reason ( at least nothing special according to request logs), and it's also very hard to be reproduced. Could it be the same issue with yours? |
What's your setup, exactly? (Backend and WSGI server?) |
@mbr Oh so sorry! I found myself mentioned wrong person. I was trying to mention @etscrivner back then. I'm using flask with gevent, using this command to run server:
And run I'm surprised when I first found some of my user logged into another's account because I was pretty sure the login part was correct. I'm now using a additional cookie to verify user session, not like session, this cookie will only be changed when a user log-in (the session in client's cookie will be changed in every request even it's not modified). And I remove blureware-admin layer from my app to make architecture simpler.
After that, I added some special logs that will let me know when a user's id in cookie is different from it's id in session. Now few days passed. I was not able to see any of these log, nor new user feedback about this issue. So I can't tell If this issue solved, or it's just not happened again yet. |
Hello, We've been experiencing this issue for about half a year. We finally got things working with the upgrade to SQLAlchemy 1.1 and using UPSERTS with postgres. Then I overrode the put operation in the SQLAlchemyStore by creating a derived class.
Finally, inject this store into the init of kvsession
I hope this helps others who have been struggling with this issue. |
@jeffcwang I'm afraid that will, at best, mask the problem by silencing the error. If User A uses Session X and it gets replaced by User B's session, also with the id X, User A and User B will still "share" a session. Your fix just silences the PostgreSQL error and makes it so that the active session will be that of B, not A. |
@mbr sorry for late response -- yes you're correct about this. It's been a while but if I recall, in our case, it was the same user that had their session over-ridden so User A == User B and it's all good. But agreed... not the best solution overall and if collisions are from diff users, could pose a big challenge. If you have any new suggestions on better fix, please let me know. |
The issue is I am fairly stumped at this point. Noone seems to be able to be able to reproduce these errors and I did review the code a while back. So far, I have only received workarounds, but not fixes for an actual bug. I think there may be some miscommunication about guarantees that are given by either the backend or simplekv. For example, in the beginning some people assumed that simplekv would turn their filesystem into a transactional database somehow (which it does not of course). I would very much love to fix this issue, but with noone being able to replicate it, there's little I can do. I'm willing to look at live systems, time permitting, as well. |
It appears that the ID generation is not sufficiently random or there is some other issue. I see frequent session ID collisions. These collisions are actually a major security risk as I'm seeing users getting logged in as other users (their session data is being overwritten by that of another user). This opens us up to a potential session hijacking problem if a malicious user can find a way to easily reproduce.
This issue is incredibly similar to a previous one (#12). Here's a basic stack trace:
Unfortunately there are no minimal steps to reproduce except to keep producing new flask sessions until the error occurs. The most consistent reproduction has been when using JMeter to do load testing.
My recommendation is that the way session IDs are generated be completely changed. You should be using something for which collisions are guaranteed to be incredibly rare - perhaps switching to UUIDs for the ID portion of the key would be better.
The text was updated successfully, but these errors were encountered: