Best Login Method
Moderator: General Moderators
Best Login Method
Hey guys.
I'm just about to start a new site.
What, in your opinion, is the best way to write and handle logins?
A) Username and password (md5'd) stored in the database, perform a lookup, then store session variables if successful?
B) As above, but sets a cookie instead of season variables as session variables time out.
Thing is, using cookies, what do I store in it? What's safe to store in it? Should I give it life for 1 hour, 24 hours, or forever?
The point of this post is to just hear how others tackle this rather simple problem...
Cheers,
Steve
I'm just about to start a new site.
What, in your opinion, is the best way to write and handle logins?
A) Username and password (md5'd) stored in the database, perform a lookup, then store session variables if successful?
B) As above, but sets a cookie instead of season variables as session variables time out.
Thing is, using cookies, what do I store in it? What's safe to store in it? Should I give it life for 1 hour, 24 hours, or forever?
The point of this post is to just hear how others tackle this rather simple problem...
Cheers,
Steve
Re: Best Login Method
Maybe, for additional security, store the ip address somewhere so when they try access the site again, from a different computer, it asks them to login again as their ip address has changed?
Thus, meanin they could only be remember at one computer at a time...
Thus, meanin they could only be remember at one computer at a time...
- social_experiment
- DevNet Master
- Posts: 2793
- Joined: Sun Feb 15, 2009 11:08 am
- Location: .za
Re: Best Login Method
Don't use MD5(), it's not secure enough. Go with one of the SHA hash algos. Add a salt to the mix. A salt (if you didn't know) is a value attached to the username or password to make their hashed value more secure in terms of it's complexity.Sjwdavies wrote:A) Username and password (md5'd) stored in the database, perform a lookup, then store session variables if successful?
Most users don't have static ip addresses so this could be a moot point (unless you are certain of the static ip).Sjwdavies wrote:Maybe, for additional security, store the ip address somewhere so when they try access the site again, from a different computer, it asks them to login again as their ip address has changed?
Sjwdavies wrote:rather simple problem...
You could try search for this topic under security posts as well, i've come across a few that will share the view of others on this subject.
“Don’t worry if it doesn’t work right. If everything did, you’d be out of a job.” - Mosher’s Law of Software Engineering
Re: Best Login Method
http://phpsec.org/articles/2005/password-hashing.html
Did you mean that sort of sha-1 and salt method?
Also, you are correct in that a user might not always have a static ip address. However, having said that, most providers will not change an ip address every day. So I still think basing the 'remember me' on a cookie is a good idea, and storing the last ip address they logged in from in the database, then looking that up when they visit the site and asking them to log back in if it doesn't match is a good idea?
I do also agree the permutations of what security measures you can put in place are endless!
Did you mean that sort of sha-1 and salt method?
Also, you are correct in that a user might not always have a static ip address. However, having said that, most providers will not change an ip address every day. So I still think basing the 'remember me' on a cookie is a good idea, and storing the last ip address they logged in from in the database, then looking that up when they visit the site and asking them to log back in if it doesn't match is a good idea?
I do also agree the permutations of what security measures you can put in place are endless!
Re: Best Login Method
1. There's no reason to prefer sha1 or md5 over stronger alternatives like sha512 or whirlpool, so I'd definitely go for either of the latter two.
2. Append long salt & pepper strings before hashing, salt being a global constant for your site, pepper being a user-specific string (randomly generated, e.g. when creating the user, stored along with the user's details). Obviously you only store these passwordhashes in your database (and the pepper strings), NEVER the password itself.
The use of salt avoids rainbow tables and complexifies brute-force attacks. Adding pepper ("user-specific salt") reduces attacks to individual hashes only, instead of attacking the entire password list at once, and makes it impossible to detect if two users happen to have the same password.
3. I recommend doing at least some form of IP-address checking. Otherwise, people's cookies may be stolen (which is basically a vulnerability of the visitors' machine, over which you have no control whatsoever).
There are several ways of dealing with this. In one case, I stored a string like this in the visitor's login cookie: "userid-xxx1-xxx2-xxx3-etc..." where each xxx value is actually a hash of the user's passwordhash + his IP (+ yet another salt & pepper). When verifying the cookie (i.e. right on top of every page with restricted access) I recalculate this hash and check if it matches with one of the xxx values. If not, it means his IP is changed (or his cookie was stolen!) and I redirect him to the login page. When logging in, I insert the corresponding xxx hash into his cookie.
This way, you have IP-restriction, yet people with multiple IP-addresses will have to login only once per IP. You may want to store only a limited number of xxx hashes in the cookie.
Instead of using the entire IP-address when calculating the xxx hash, you could use the most significant 20 bits or so, avoiding inconvenience for people with dynamic IPs (which are typically within an ISP's limited IP-range, so only the lower bits will vary). This comes at the cost of some security though, as anyone within the same IP-range could then use the same cookie.
4. Of course use SSL (https) at all times.
2. Append long salt & pepper strings before hashing, salt being a global constant for your site, pepper being a user-specific string (randomly generated, e.g. when creating the user, stored along with the user's details). Obviously you only store these passwordhashes in your database (and the pepper strings), NEVER the password itself.
The use of salt avoids rainbow tables and complexifies brute-force attacks. Adding pepper ("user-specific salt") reduces attacks to individual hashes only, instead of attacking the entire password list at once, and makes it impossible to detect if two users happen to have the same password.
3. I recommend doing at least some form of IP-address checking. Otherwise, people's cookies may be stolen (which is basically a vulnerability of the visitors' machine, over which you have no control whatsoever).
There are several ways of dealing with this. In one case, I stored a string like this in the visitor's login cookie: "userid-xxx1-xxx2-xxx3-etc..." where each xxx value is actually a hash of the user's passwordhash + his IP (+ yet another salt & pepper). When verifying the cookie (i.e. right on top of every page with restricted access) I recalculate this hash and check if it matches with one of the xxx values. If not, it means his IP is changed (or his cookie was stolen!) and I redirect him to the login page. When logging in, I insert the corresponding xxx hash into his cookie.
This way, you have IP-restriction, yet people with multiple IP-addresses will have to login only once per IP. You may want to store only a limited number of xxx hashes in the cookie.
Instead of using the entire IP-address when calculating the xxx hash, you could use the most significant 20 bits or so, avoiding inconvenience for people with dynamic IPs (which are typically within an ISP's limited IP-range, so only the lower bits will vary). This comes at the cost of some security though, as anyone within the same IP-range could then use the same cookie.
4. Of course use SSL (https) at all times.
Re: Best Login Method
@Apolo:
Thanks for the reply, could you elaborate on point 3? And maybe give an example of point2?
Sorry to be a pain
For example, could the pepper be the unixtimestamp of when the account was created?
Thanks for the reply, could you elaborate on point 3? And maybe give an example of point2?
Sorry to be a pain
For example, could the pepper be the unixtimestamp of when the account was created?
Re: Best Login Method
Exactly what do you not understand or need further explanation about?Sjwdavies wrote:@Apolo:
Thanks for the reply, could you elaborate on point 3?
And maybe give an example of point2?
Code: Select all
$salt = 'SoMe_HaRdCoDeD_StRiNg';
$pepper = uniqid(mt_rand().time(),true);
$passwordHash = hash( 'sha512' , $userPassword.$salt.$pepper );
// now store $pepper and $passwordHash in the database for this particular userSure, anything that is unique for this user will do.For example, could the pepper be the unixtimestamp of when the account was created?
Re: Best Login Method
@Apollo: Could you perhaps give an example of point 3? Sounds like what I'm trying to achieve.
Thanks for the example of point 2, would the pepper in that example always e a fixed length? Or would it not matter on it's length - because you just rehash it and add it on the end of the hashed string to check when logging in?
Thanks for the example of point 2, would the pepper in that example always e a fixed length? Or would it not matter on it's length - because you just rehash it and add it on the end of the hashed string to check when logging in?
Re: Best Login Method
When logging in, after having verified that the password was OK (that is, the $passwordHash you calculated from the entered password matched with the hash for this user in the database), you do this:Sjwdavies wrote:@Apollo: Could you perhaps give an example of point 3?
- $loginHash = hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper );
- get list of hashes from cookie (if available)
- insert $loginHash into this list if it wasn't in there already (probably not, otherwise you wouldn't have to login)
- store userID + new list of hashes in cookie
At the top of each password-protected page, you do:
- get userID + list of hashes from cookie (if not available, redirect to login)
- get $passwordHash for userID from database, and do $requiredHash = hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ); // same as $loginHash above
- if $requiredHash is present in the list of hashes from the cookie, show the page, otherwise redirect to login
No it doesn't really matter. You simply append it to the raw password and the normal (constant) salt string. See also example in previous post.Thanks for the example of point 2, would the pepper in that example always e a fixed length? Or would it not matter on it's length - because you just rehash it and add it on the end of the hashed string to check when logging in?
Re: Best Login Method
No it doesn't really matter. You simply append it to the raw password and the normal (constant) salt string. See also example in previous post.[/quote]Thanks for the example of point 2, would the pepper in that example always e a fixed length? Or would it not matter on it's length - because you just rehash it and add it on the end of the hashed string to check when logging in?
Sorry, gonna take this one at a time to avoid confusion
So basically, the $passwordHash would look like: passwordHashed . constant(salt) . unixTimestampHashed?
For example?
Re: Best Login Method
So you'd do something likeApollo wrote:When logging in, after having verified that the password was OK (that is, the $passwordHash you calculated from the entered password matched with the hash for this user in the database), you do this:Sjwdavies wrote:@Apollo: Could you perhaps give an example of point 3?
- $loginHash = hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper );
- get list of hashes from cookie (if available)
- insert $loginHash into this list if it wasn't in there already (probably not, otherwise you wouldn't have to login)
- store userID + new list of hashes in cookie
Code: Select all
set_cookie('loggedIn', hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ));
Last edited by Sjwdavies on Tue Jan 04, 2011 4:00 pm, edited 1 time in total.
Re: Best Login Method
You're referring to a list of hashes, but don't you just mean the one long $loggedinHash that's stored in the cookie?Apollo wrote:At the top of each password-protected page, you do:
- get userID + list of hashes from cookie (if not available, redirect to login)
- get $passwordHash for userID from database, and do $requiredHash = hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ); // same as $loginHash above
- if $requiredHash is present in the list of hashes from the cookie, show the page, otherwise redirect to login
Re: Best Login Method
No, if $password is the original, raw password as entered by the user in the signup or login form, and $salt is some constant string, and $unixTimeStamp is the user join date (or anything that you store in the user database), thenSjwdavies wrote:So basically, the $passwordHash would look like: passwordHashed . constant(salt) . unixTimestampHashed?
$passwordHash = hash('sha512', $password.$salt.$unixTimeStamp );
And $passwordHash is stored in the user database.
Not exactly, my cookie string looks like this:Sjwdavies wrote:So you'd do something likeCode: Select all
set_cookie('loggedIn', hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ));
"UserID-LoginHash1-LoginHash2-LoginHash3-...-LoginHashX"
Where userID is just the database id for the supposedly logged in user, and each LoginHashX is one hash of the user's PasswordHash + an IP address.
If the user has logged in from 3 different IP addresses, he'll have 3 LoginHash values in his cookie. So it's a list, but stored in 1 string.
(Extract and compose the list from / into the cookie string with explode and implode or something).