Your cookies are borkt. Seriously.

Sunday, 02 February, Year 6 d.Tr. | Author: Mircea Popescu

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 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 ?!

  1. Don't start with "but herp MP, https!" Https is http for the needs of this conversation. []
  2. 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. []
  3. 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. []
  4. 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. []
Category: Meta psihoza
Comments feed : RSS 2.0. Leave your own comment below, or send a trackback.

3 Responses

  1. If by cookie stealing you mean stealing it from the client computer, yes. Otherwise you can still eavesdrop.

    If you chose to invalidate each older nonce after new requests, you're going to have to store them. Why not. However you're probably going to have to handle users opening multiple pages at once, and having multiple browsers (not that hard, store a cookie to distinguish which browser is which). And in the end, the attacker can still make a request instead of you, he just has to make the next request before you do.

    In the end, you have a system that is overkill if you want to prevent stealing the cookie from the computer, and isn't enough to protect from eavesdropping; the time based tokens are enough and transport security should take care of the rest.

    Any better solution would require browser cooperation or JavaScript.

  2. Interestingly, you can compare browsers and SSH.

    SSH doesn't lie to you. When you connect for the first time to a server, it doesn't accept the certificate, and displays the fingerprint for you to check. Browsers trust external services, where any of them has ultimate authority.

    SSH allows you to use a password, or better, a client side-key. (Actually, you can do even more custom stuff if you want.)
    SSH is stateful, though you can use it for one-time requests if you want to.
    Browsers have nothing of the sort; users have to authenticate with things than can be replayed.
    Added bonus: multiplexing.

  3. Mircea Popescu`s avatar
    Mircea Popescu 
    Sunday, 2 February 2014

    No but look,

    he just has to make the next request before you do

    Something as simple as a confirm page becomes an unsurmountable obstacle to the attacker.

    So he's made the request before you do, and updated your cookies. Now what ? He has to get you to let him ride again, and he doesn't have enough info to construct the request he needs anyway.

    If you chose to invalidate each older nonce after new requests, you’re going to have to store them. Why not.

    which are a) stored

    You only store the latest. There's no requirement that you support tabbed browsing in your logged in site, for one. If what the guy is doing is surfing pics he doesn't actually need to be logged in. If what he;s doing is banking you don't need five tabs open.

    Moreover, you can serialize the requests like anything else, after all simultaneity doesn't exist in the real world. For that matter you can simply log him out if you get requests faster than one a minute, why not ? Nobody said security is convenient to any arbitrary degree of convenience. Let the user learn this.

    and isn’t enough to protect from eavesdropping

    There's no way to protect http from eavesdropping, it's designed to be and functions as a plaintext channel. You can either implement end to end encryption like MPEx or else learn to live with the fact - the fact that your communication is plaintext. No matter what you do. A fine example here is the fate of the SR pile of fail (and for that matter : some of the latter scriptkiddies vieing to fill that void of fail actually came up with models such as "paste your gpg secret key in here for security". Not kidding!)

Add your cents! »
    If this is your first comment, it will wait to be approved. This usually takes a few hours. Subsequent comments are not delayed.