PHP "Remember Me" security flaw?
Asked Answered
N

4

12

I'm in the middle of coding a 'remember me'-equipped login form, and so far the tutorials I've read (partly to make sure I'm doing it right) all say to store the encrypted password in a cookie along with the username. Then, each time PHP checks if the current user is not logged in, check their cookies and look for those values. If the username matches the password, you're in.

To me, this is a gaping security hole. If somebody were to hack the database or somehow get access to the encrypted passwords, they wouldn't even need to crack them. Just set your own cookies and go. Am I correct, or just being paranoid?

My login system uses sessions to keep track of the current user id, and a 1/0 for a quick logged in/logged out check. The user can't edit sessions AFAIK, so this is secure (if it's not, please let me know). I was thinking of just storing the session ID in a cookie, to later resume it, but that's also not secure.

I care a lot about the security of my users, how can I properly protect their information while still maintaining a functioning website?

Neurophysiology answered 2/1, 2013 at 23:28 Comment(6)
I wouldn't store the encrypted password, just the user_ID in a cookie that expires in X days. For "sensitive" areas (account/profile management, for example), you can require them to login if they don't have a valid $_SESSION (which you should set when they do login).Detrusion
How are you currently storing session ID if storing it in a cookie is "not secure?"Austrasia
@georgefox currently, I'm not storing the session ID in anything, I was just saying it's a possibility for the remember me function.Neurophysiology
Theory & idea: I would just set the cookie expires time for the session to a default amount of time, then if users check the "remember me" option, make the cookie that calls the user session persist longer.Cracow
@Detrusion might work, but when you leave the website or close the browser (one of the two, I forget) the session is lost.Neurophysiology
@Jaxo, in order for your sessions to work, the client has to keep sending you his or her session ID. This is almost always done by setting the session ID in a cookie (e.g., PHPSESSID), which the client sends back with every request to your domain. This is all handled by PHP internally, and it's configurable in php.ini. You're probably not explicitly doing anything with the session ID, but PHP is storing that session ID in a cookie for you.Austrasia
D
11

Usually when the server is requested to remember the user, it issues an additional cookie beside the normal session cookie, and this new string contains the username and a reasonable amount of random characters which make it unguessable. This is obviously saved in the database (for security reasons you may want to treat it like a password and thus salt and hash it), and the next time the user connects with the same browser (assuming the old session expired) the application receives the random string, checks the database, and if there's a match the user is authenticated.

An alternative is moving the session expiration time ahead of some amount.

What are the security holes here? Provided you use a good random generator, the only thing that can happen is that the user accesses the application from a shared browser and doesn't manually logs out when it ends.

The normal rules always apply since you are on an insecure channel: use HTTPS, otherwise whoever sits in between your computer and the server can steal cookies (either the session one or the remember-me one) and act as if it were you.

Bonus, this must-read by Jeff Atwood

Doctrinaire answered 2/1, 2013 at 23:37 Comment(1)
This seems like a good way to go, thanks! Also, reading that monster login post now!Neurophysiology
H
2

Never save passwords in any way (encrypted password which can be used to login is still a password) on client.

Use randomly generated key, safely stored on server. These keys can be revoked later unlike the encrypted passwords which will be valid until changed.

Using php you can generate random key like this md5(uniqid(mt_rand(), true)). For better safety store it salted and hashed in db.

Example table:

login_keys (
  user_id int,
  key char(40), # sha1
  salt char(15)
)

Also note you should enable the HTTP only cookie option.

Hizar answered 3/1, 2013 at 0:17 Comment(0)
V
0

If you want it secure, dont allow your users to keep them logged in.

When setting the session, make sure to bind the ipaddress to the session ID, so that if someone picks up a session later, it can only be done from the same Ip address. Yo can do this by keeping a database with (hashed) session ids + hashed ipaddresses. I use phps function http://php.net/manual/en/class.sessionhandler.php to set a session handler and match sessions with ipaddresses.

Vidda answered 2/1, 2013 at 23:40 Comment(1)
Ip addresses are not intended to be used for security and you cannot trust ip addresses. IP check, as you point out, still makes life harder for the bad guys though.Globigerina
U
-3

I have encountered this same issue while working on my own website, the best way I found to solve it was to simply not remember passwords, only usernames, providing a faster loggin but not a less secure one. The fact is that there is no sure fire way to keep the passwords absolutely secure. Besides with new browsers, the user can have their browser remember it.

But if you must have a saved password, try this:

Have multiple cookies, 2 would be the easiest, and use one for an encrypted password, while the other held an encryption key. The password in the database would hold a further encrypted password, obtained by using your stored encryption key(s). When you are ready to check the password, extract the values and encrypt the password.

Hope this was helpful. Good luck!

Edit: I might have misunderstood this, if the user is still logged in, it is good practice to store a session variable.

Unteach answered 2/1, 2013 at 23:37 Comment(2)
Never save password in any way (encrypted password which can be used to login is still a password) on client. Only save the key stored on server. These keys can be revoked later but the encrypted password will be valid until changed.Hizar
That isn't necessarily true because one would set an expiration date; however, I would rather not use my second method.Unteach

© 2022 - 2024 — McMap. All rights reserved.