I probably misunderstand your point, because I’m about to say something obvious. Requests that belong to the same session are not guaranteed to be sequential in any meaningful way.
The check you are talking about would have to check the session against SOMETHING. Something more specific than a single secret. I.e., a piece of server-side data that maps to the session. Which kills the rationale behind session-based cookies, no?
So, it looks like cookie-based sessions would only work for the same scenarios where “Remember my login on this computer” option without an opt out is acceptable.
Now, I click "Log Out", and get up from the library's computer, only
to let the person waiting after me to retrieve the old cookie.... That
innocuous user id just became both sensitive and transient.
You click 'log out' and it deletes the cookie.
This is no different to a normal server-based session.
Actually, if you have the cookie set to expire at the end of the
session, simply closing your web browser should delete the cookie.
Oh, but it is. With a server-based session, I "Log Out" and my session can be purged from the server, leaving the old session ID worthless. With cookie sessions, the cookie is still valid to the server even if deleted from the browser's cookie repo. There is no way to selectively expire sessions from the server.
Server-side: someone gets my session ID, I log out, they present the session ID to the server -> worthless.
Client-side: someone gets my session cookie, I log out, they present the cookie to the server -> impersonation!
You're forgetting that:
(a) sessions already use cookies to store the session ID, so any
issues with cookie interception or other attacks apply to all session
storage methods.
(b) you can't change the contents of the cookie or it will fail the HMAC.
If you're overly concerned with "user_id" haxoring, just use a guid
instead of DB id in your User.find
Umm... did you read the thread? No, I'm not forgetting any of that, and those are not my points at all.
(a) Cookie sessions are vulnerable to replay attacks, because the client can present *any* cookie that it has seen to the server, not just the most recently sent one. On the other hand, server-side storage methods are not vulnerable because the session ID always references the latest version of the session.
(b) Of course the HMAC would fail if you change the session. I'm not talking about changing the session. I never was. What worries me is this:
1. I log in; I get session cookie A which corresponds to "user_id=12345" with the HMAC and everything.
2. I log out and my session cookie is "deleted" -- in the sense of not being presented to the server anymore. It may hang out on disk or memory.
3. Someone finds the session and presents it to the server. Since it is signed by the server, it is accepted and that user is logged in.
Suddenly, a token which had no value after logout (a session ID) now has immense value (session cookie) because possession of it allows one to impersonate me at any time in the future.
It's possible mitigate the problem somewhat by having an expiration
time put into the session (which cannot be modified by an attacker due
to the HMAC). However, you still won't be able to manually expire
sessions (i.e. log out).
This is the best idea I've seen so far, but it still requires balancing the attack window (as small as possible) against the maximum allowed time between requests. Given that replay attacks can be automated, the acceptable values for these numbers may or may not overlap, depending on the application.
You're forgetting that:
(a) sessions already use cookies to store the session ID, so any
issues with cookie interception or other attacks apply to all session
storage methods.
Not true. Example: if, on logout, you update the session in the DB to
state "No User", the cookie is worthless.
(b) you can't change the contents of the cookie or it will fail the HMAC.
Yes, but you can replay them. See my first post.
If you're overly concerned with "user_id" haxoring, just use a guid
instead of DB id in your User.find
This will only help in cases where the attacker wants to steal
someone's identity. But there are other uses of a replay attack -
like the example I initially mentioned - where this won't help at
all. And even in the identity theft case - what's to stop the
attacker from using the computer 5 minutes after I leave?
In general, I'd offer the amount of confusion on this thread as the
best evidence that the average developer shouldn't have to deal with
these issues by default.
This was discussed earlier in the thread. The problem is that such a nonce
would require communication between the backend servers via DRb or the
database, which removes any benefit from storing the cookies client-side.
You might as well store the whole session in the database or DRb store.
Avoiding a single database lookup isn't the purpose of the cookie store.
As for the opt-in, if you're the type of user that would know enough about
security to opt in to such a plan, you're probably not storing account
balances in a client-side cookie. The discussion we are having concerns
sensible defaults.
This discussion skipped plugging the session replay hole. I understand
your concern, but I think you underestimate the average Rails
developer.
For example: to prevent user_id replay, store a last access timestamp
in session that's updated on login and logout.
So does this mean that I can’t use the cookie for client side
javascript? If I want to use it to keep track of some client side
script, then I can’t? Is that true?
Avoiding a single database lookup isn't the purpose of the cookie store.
It's worth remembering the downsides to our current default.
Deploying to a 'real' production setup with it is a shortcut to a
heart attack. File locking, mongrel deadlocking, NFS churn. All of
those are real problems which hurt developers every day.
That most applications *already* change their session store indicates
that it's not that big a deal. If you're currently doing something
which is incompatible with the assumptions of the cookie store,
switch. I'm still using sql sessions and intend to continue doing so
:).
This was discussed earlier in the thread. The problem is that such a nonce
would require communication between the backend servers via DRb or the
database, which removes any benefit from storing the cookies client-side.
You might as well store the whole session in the database or DRb store.
Avoiding a single database lookup isn't the purpose of the cookie store.
Sure, but you do remove a lot of the glamour of the cookie store if it has to be tied to a database for a nonce lookup anyway.
As for the opt-in, if you're the type of user that would know enough about
security to opt in to such a plan, you're probably not storing account
balances in a client-side cookie. The discussion we are having concerns
sensible defaults.
This discussion skipped plugging the session replay hole. I understand
your concern, but I think you underestimate the average Rails
developer.
I might be over-concerned here, but I'm not talking about the average Rails developer. I'm talking about the worst ones. I can tell you that while the average Rails developer I've worked with would certainly be able to understand this and work around it, I'm not sure that the worst ones would even understand what the issue was if it were explained to them.
For example: to prevent user_id replay, store a last access timestamp
in session that's updated on login and logout.
If I understand you correctly, you would also keep a copy of the latest timestamp server-side. I would submit that for many developers, storing a timestamp for each session on the server is not much more attractive than just storing the whole session on the server.
This is a good point. The CookieStore is a major improvement over PStore from a functional perspective. We are arguing over things that are important to discuss, but still very, very small compared to that.
In Mongrel? But only one Mongrel can know that without them talking to
each other.
In the DB? So we need to hit the DB each time, only we need to do it
manually?
In a temp file? That's back to the default session store.
In the cookie itself? We haven't solved the problem. If the attacker
fishes out an older cookie - and, believe me, they're still on the
disk - he does a replay attack.
I think this is a fair question: most of the people arguing that
cookie stores are safe have also pointed out that they're not crypto
experts. Or security experts. Which is fine - I'm sure their top
notch developers. Before making something which relies on crypto the
Rails default, doesn't it make sense to have at least _one_ crypto or
security consultant review it? Perhaps Schneier will take a look...
I think this is a fair question: most of the people arguing that
cookie stores are safe have also pointed out that they're not crypto
experts. Or security experts. Which is fine - I'm sure their top
notch developers. Before making something which relies on crypto the
Rails default, doesn't it make sense to have at least _one_ crypto or
security consultant review it? Perhaps Schneier will take a look...
If you'd like to coordinate this, I'd definitely be glad to hear from
them. As it stands I think your complaint boils down to the lack of
server-side invalidation of a session. Most everything else flows
from that. I'm not sure that there's a shared nothing way to take
care of that, but the crypto experts would know for sure.
Please do investigate having someone conduct a review.
That most applications *already* change their session store indicates
that it's not that big a deal.
My feeling (this is what I did) is that this happens because they *got bitten* by the default session store problems, the effects are visible (mainly the performance issues).
If you're currently doing something
which is incompatible with the assumptions of the cookie store,
switch.
this could be solved by clearly documenting this assumptions (and perhaps giving suggestions)
I'm still using sql sessions and intend to continue doing so
:).
hmm... how about defaulting to these (at least for the production environment)?
Pulling two IDs (session id + nonce) from the DB is better than
pulling 80k that could go in cookies. Why not include nonce in the
default, and if the developer wants the blazing speed (and
corresponding dangers), they can disable it?