2

I have a user database that stores encrypted passwords, and would like to create a "Keep me logged in" cookie. I believe the following method should be secure enough for my purposes, but I would like to hear your thoughts:

  1. If the user selects the "Keep me logged in box" and provides proper credentials, create a cookie that contains a very large random string (call this the beacon). This is also stored in a separate column in the user table.
  2. Each time a user visits the page, search the user table for the beacon cookie. If it doesn't exist, do nothing. If it does exist, retrieve the user's information and treat them as logged in.
  3. When the user logs out, or logs in without the box checked, destroy the beacon cookie.

This could be manipulated if someone were to properly guess the beacon string, but my intent is to make it large and random enough that this is very difficult to do.

Nick S.
  • 353
  • 3
  • 13
  • have you ever looked into how [sessions](http://php.net/manual/en/ref.session.php) work? – ಠ_ಠ Jan 21 '13 at 21:22
  • 1
    I hope your database stores 'hashed passwords' rather than merely 'encrypted' passwords. I'd echo the previous comment and make sure that you aren't making a custom version of something that already exists - 'random' sources and 'large' enough are well defined. – Philip Whitehouse Jan 21 '13 at 21:25
  • 2
    @zdhickman If you are trying to keep a "session" beyond the normal session expiration, you need to implement something like this. – datasage Jan 21 '13 at 21:25

3 Answers3

2

I presume this is being done in addition to normal session handling as way of recreating the session later.

There are a few things that can be done to improve security.

  1. Use SSL, makes cookie interception much more difficult.
  2. Regenerate the cookie hash after each use. It should only be valid for one login.
  3. If you store this as 1 cookie to 1 user, it won't work if the user is on multiple devices (Cookie from first device gets overridden by cookie on second device).
  4. Hash needs to be random, should not incorporate any user data in generation.
  5. User data (email, password in particular) should require a password to change. If the cookie is intercepted, the interceptor wont be able to change data on the account.
datasage
  • 19,153
  • 2
  • 48
  • 54
  • In addition to 4.: while the hash (your "beacon") must be independent from user data, the cookie must contain login hash AND user name. It was not clear from your description if you planned to do so - you would not let someone login with a password without user name, would you? – Fabian Schmengler Jan 21 '13 at 21:40
  • @fab I assume the hash would be unique, in which case that would be unnecessary. – datasage Jan 21 '13 at 21:41
  • I disagree, it is not just about uniqueness. If the user base is large enough, a brute force attack would just need some luck to get access to a random account. – Fabian Schmengler Jan 21 '13 at 22:02
  • If you make your key based 32 hex digits. You would have 16^32 combinations to test. Provided that the key is sufficiently random. – datasage Jan 21 '13 at 22:15
  • That would be (16^32 / number of users) - but I admit, I had my math wrong, it does not matter that much. – Fabian Schmengler Jan 21 '13 at 22:20
0

It sounds like you're trying to recreate sessions from scratch. Why not just pass session_set_cookie_params() the really long timeout?

Greg
  • 12,119
  • 5
  • 32
  • 34
0

I think this is not the best way to implement a 'remember me' cookie. Making the hash larger is not the solution.

Think saving something more in your cookie.

You suggest this:

'a89bd752123cde09'

If you have many users, maybe it's not so difficult as you think to get a valid token

If you simply add an user ID to this hash...

$userID . '-' . 'a89bd752123cde09

Now, they need to get a valid token associated to the correct user ID, we have made it a little bit complicated

You can concatenate something about the user's browser or session too, and encrypt it, maybe somthing like this:

hash_hmac('sha256', $userID . '-' . 'a89bd752123cde09' . '-' . md5(timeStamp when remember expires) . '-' . md5(browser user agent), A_SECRET_KEY);

When you check the cookie dencrypt it and check the data is correct.

It's not the best solution, but I think it's better. There is many info about web security, read about it and don't implement this directly.

artberri
  • 1,327
  • 13
  • 26