Let's start with a conversation :
mircea_popescu So since pretty much anyone here has a better knowledge of webstuff than I do, here's a question : Inasmuch as you're going to do a site with accounts, which people can log in over http (stupid as this may be)i wouldn't the best practice be, that upon user registration you generate a user salt and a nonce, send these as a hashed cookie, and upon each subsequent login you a) check if the user has the old cookie ; b) hash the salt, store it, increment the nonce, store it ; c) send a new cookie ? If your salt+nonce -> cookie process is deterministic you can even verify it's the same actual user to any arbitrary degree of fineness (such as, same ip or w/e). The question being, is anyone currently doing this ? (Obviously in this case by "login" I mean, any http request to your server at all)ii.
[A little later]
pankkake Most websites, and almost all frameworks I've seen, only use a cookie that isn't refreshed, and is either left to expire stupidly, or never expiring. If you add a signed timestamp to the cookie, maybe you can limit logins from old stolen cookies.
mircea_popescu So then this'd be beyond my comprehension. Why in the fuck ? Obviously you have to chain cookies if you're using that retarded method of keeping track of user state.
KRS- Good luck with that cookie strategy if you are using multiple web servers.
mircea_popescu What'd be the problem ?
pankkake It's a signed cookie, not session cookie; and managing sessions over multiple servers is possible too. But usually the process is that you have an auth cookie (lifetime = high), and a session cookie (lifetime = short) and we're only talking about the auth cookie.
nubbins` Managing sessions over several servers is commonplace.
mircea_popescu So is the session cookie changed on each pageload ?
pankkake No, it doesn't change, that's the point. Unless you store session data in it, but usually it's just a secret ID.
mircea_popescu Well that's fucktarded.
KRS- Load balanced web servers would associate that cookie to one particular web server, if the load balancer stategy isn't carefully chosen (if possible) when the load balancer shifts traffic the cookie could become invalid beecause another web server doesn't know about the cookie.
nubbins` ^ have seen this. Had to troubleshoot a web app once where there was a round-robin load balancing setup. each new page request launched a new session, up to a max of 3 (the number of servers).
mircea_popescu KRS- Inasmuch as they all run your code they all know about the cookie.
KRS- I've dealt with this problem before. You have to carefully pick a load balanced strategy or pick another session persistence.
mircea_popescu Why so much derp ;/
[A little even later-er]
pankkake http://docs.pylonsproject.org/projects/pyramid/en/latest/api/authentication.html see reissue_time, it looks like those guys thought of it too :) Sadly the gpg over http projects seem to go nowhere.
Now, let's try to specify this thing.
1. Users create new accounts on your site through whatever process, such as mailing you their last electricity bill and pictures of random wall patterns, or their amputated thumb and foreskin. If you're not a medieval outfit somehow inexplicably stranded on the Internet 500 years after your expiry date, the process will include PGP signatures.
2. Users "log into" their accounts, which is to say they register new stateful sessions with your webserver over the stateless protocol known as http[s]. This could be done in whatever manner it's currently done, which definitely sucks but doesn't make up a topic of this conversation.
On the server side you generate a salt for each user (S), and null a nonce (N).iii, which are a) stored ; b) put through C(S, N, Xiv) which generates a cookie which is sent to the client.
3. Users make requests to your server, which is to say, log into it. By, for instance, accessing a page.
On the server side, you take your S, N (and if X is not null, the observer X), calculate the C, compare it to the C the client reports. If they don't match you redirect the client to 2. If they do match you hash the S (with a salt!), obtaining S'. You increment N, obtaining N'. You adjust X if needed. You calculate the new C(S', N', X') and send it to the client.
This very simple yet universally ignored security model ensures :
- No cookie stealing. You can publish everyone's cookies in plain view for all the good it's going to do anyone.
- Much easier to limit session riding. Something as simple as a confirm page becomes an unsurmountable obstacle to the attacker.
- New login kills old cookies, definitely. This may seem like hardly worth the mention until you consider all the edge cases of cookie expiration. It will save you time and code, yo!
- You can display a definite and binding pagecount for that session somewhere your client can see it on the page and appreciate your unmatched security focus. Because unlike all the other idiots out there saying the words "security focus", you demonstrate the actual thing. Big, big difference.
Just scratching the surface here. Seriously people, stahp! What r u doing ?!———
- Don't start with "but herp MP, https!" Https is http for the needs of this conversation. [↩]
- That's right : whenever your user is "logging in" you're in fact looking at a registration event. Whenever he's asking for a new page, any new page whatsoever, you're looking at a login event. The fact that common parlance in the field is blind to this reality doesn't exactly plead in the favour of that group's intelligence, at least not in the eyes of security people. [↩]
- There is no benefit to using a value other than null. The salt should ideally be obtained by hashing the output of an actual RNG. PRNGs are not nearly as good, and besides, RNGs are not expensive - any webserver handling user "logins" should have a dedicated RNG. Which does not mean "an Intel diddled on-chip piece of crap", by the way. [↩]
- X may be whatever information about the user's system you may wish to obtain. It could be their IP. It could be the content of a hidden form field. It could be anything you wish it to be and it can definitely be null. [↩]