1

I could not find writeups about secure cookies so I have done some thinking. (I already have a "secure" password database with bcrypt and salt)

Steps:

  1. User logs in
  2. Save user IP + randomstring in memcache example (key = IP value + randomstring + username)
  3. Create a new string username + ip
  4. Cipher this string with blowfish , the cipher key will be the randomstring stored in the memcache
  5. The user receives a ciphered cookie
  6. If the user comes again to my site and has a cookie -> I check if his IP is in the memcache, if yes take the value which is randomstring & username
  7. Try to decipher the cookie value with the randomstring
  8. Check if the request-IP and IP stored in the cookie are equal, and usernames are equal. (username from cookie vs username from memcache)
  9. If success, log in

What do you think?

Now there are two thing that I worry about:

  1. Can IP requests be faked ?
  2. Is my memcache secure?
Rory Alsop
  • 61,367
  • 12
  • 115
  • 320
Maik Klein
  • 195
  • 5
  • 1
    Thats silly, why would you prevent a user from seeing their own cookie? –  Jul 11 '12 at 11:42
  • 1
    And why would you refuse to allow a user to log in just because their IP address changed? – David Schwartz Jul 11 '12 at 15:13
  • Because I thought that someone could steal the cookie. So I wanted to check if the ip's are equal. Is this wrong ? – Maik Klein Jul 11 '12 at 15:19
  • 2
    IP addresses can change in the middle of a session for a number of reasons. Usually sites don't block access or require re-authentication for this. And to answer your question, yes, the source IP address can be spoofed. – Mark Jul 11 '12 at 15:21
  • 1
    @MaikKlein: Yes, it's very wrong. For one thing, if a different caching proxy issues the request on behalf of the user, the IP address will change and logins won't work. And if you rely on it for needed security properties, people who share NAT with untrusted users will be vulnerable. (If you don't need it, why do it? If you need it, you're screwed whether you do it or not.) – David Schwartz Jul 12 '12 at 10:58

3 Answers3

4

Why on earth you want to store any credentials (even ciphered) on the client-side? The much better idea is to keep everything in sessions.

Moreover, if you want to think about cookies security, you cannot forget about flags like: Secure and HttpOnly.

HttpOnly - this one protects us from any kind of XSS vulnerabilities. This means, that cookie with this flag cannot be accessed through client side script (of course it works only for browsers which support this flag - nowadays, almost all of them).

Secure - this flag "forces" browser to use cookies only when secure/encrypted connection is set.

p____h
  • 1,527
  • 7
  • 11
3

The short answer. Your mechanism is too complicated. There is a simpler, better, more secure solution: use SSL site-wide, and set the secure bit on all your cookies so they will only be sent over encrypted (SSL) connections.


Technical nitty-gritty. If you really want to discuss your proposed mechanism, we can talk about it, but I think the specific technical shortcomings in it are secondary to the more general point that there's a simpler, better way to do it. Here are some specifics:

If you fix these flaws, your proposal is not entirely unreasonable. For instance, ASP.NET supports encryption and authentication of cookies using a MachineKey.

However, I do not recommend you take this path. While you could probably fix these flaws given engouh effort, I'd suspect the complexity of inventing how to do this properly is probably more than you are qualified for. This is tricky stuff, and it would be easy to get something wrong. (For instance, witness the devastating flaws in ASP.NET's encryption, which allowed padding-oracle attacks to decrypt everything and defeat the security of all of the crypto.)


General advice. Instead of trying to do something funky with encrypting your cookiess, I'd suggest the following advice:

  • Generally speaking, be reluctant to store state in cookies. Instead, store it in the session or in the database. That way, all you need is a session cookie.

  • Use your web programming framework's built-in session management support; don't try to roll your own. (If you try to roll your own, you can easily end up with vulnerabilities like session fixation.)

  • Use SSL sitewide. Set the secure flag on all cookies.

  • Use CSRF defense for all POST requests. Make sure that all GET requests have no side effects (side-effecting requests should be sent as POSTs).

  • Read OWASP's materials on web application security.

D.W.
  • 98,420
  • 30
  • 267
  • 572
2

The general solution i use for securing cookies and pages are

  • Use HTTPS for logins and private pages like PMs (or have the entire site https)
  • Send back a Secure and HTTP only cookie with a 'login' or 'auth' token (we check if it matches the user). This token is used for private pages like PMs.
  • Send back another login/auth token thats http only but non secure so it can be used for non https pages (this is optional. But if you like to display the username, messages or allow a user to post public comments there has to be a way to auth them so this may be required if you want that on non https pages)
  • Use a WantHttp cookie so if a user clicks a link to a non http version of the site he will automatically be redirected to the https version
  • Have a CSRF token which every form in every page uses. Randomly chosen but not the same across all user (non constant)
  • Have that same CSRF token as a HTTP only cookie. Everytime a POST request happens check the form and cookie to see if they match. No lookup in the DB required (just look at cookie and form values). If they don't match an attacker is trying to automatically send request on the users behalf. Attackers can not know what the users token is as they cannot request pages and read them. They cannot see the httponly cookie with js. They may request a http page while sniffing packets and read your cookies. In which case always use https on every page with a form and mark the token cookie as secure.
  • okay thanks , didn't know about CSRF yet :). But one question, you are talking about tokens, i guess this some randomstring that matches somthing (like a user) ? – Maik Klein Jul 11 '12 at 12:29
  • The token doesn't need to match anything. They just need to match eachother ;). I personally check the cookie submitted when a user GETs the page and if there isn't a token i randomly give them one in the http response. –  Jul 13 '12 at 02:55