Best Login Method

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Best Login Method

Post by Sjwdavies »

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
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

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...
User avatar
social_experiment
DevNet Master
Posts: 2793
Joined: Sun Feb 15, 2009 11:08 am
Location: .za

Re: Best Login Method

Post by social_experiment »

Sjwdavies wrote:A) Username and password (md5'd) stored in the database, perform a lookup, then store session variables if successful?
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: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?
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:rather simple problem...
;) It is everything but simple. The amount of 'security checks' that you could implement is quite possibly limitless. Something to keep in mind is users. How will your tight security affect useability and will it serve to stop people from using your site / application as opposed to stop illegal activity against your accounts / system.

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
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

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!
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Re: Best Login Method

Post by Apollo »

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.
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

@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?
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Re: Best Login Method

Post by Apollo »

Sjwdavies wrote:@Apolo:

Thanks for the reply, could you elaborate on point 3?
Exactly what do you not understand or need further explanation about?
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 user
For example, could the pepper be the unixtimestamp of when the account was created?
Sure, anything that is unique for this user will do.
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

@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?
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Re: Best Login Method

Post by Apollo »

Sjwdavies wrote:@Apollo: Could you perhaps give an example of point 3?
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:

- $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
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?
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.
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

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

Sorry, gonna take this one at a time to avoid confusion :D

So basically, the $passwordHash would look like: passwordHashed . constant(salt) . unixTimestampHashed?

For example?
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

Apollo wrote:
Sjwdavies wrote:@Apollo: Could you perhaps give an example of point 3?
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:

- $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
So you'd do something like

Code: Select all

set_cookie('loggedIn', hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ));
Which would just result in one massive string?
Last edited by Sjwdavies on Tue Jan 04, 2011 4:00 pm, edited 1 time in total.
Sjwdavies
Forum Commoner
Posts: 25
Joined: Mon Nov 17, 2008 10:18 am

Re: Best Login Method

Post by Sjwdavies »

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
You're referring to a list of hashes, but don't you just mean the one long $loggedinHash that's stored in the cookie?
User avatar
Apollo
Forum Regular
Posts: 794
Joined: Wed Apr 30, 2008 2:34 am

Re: Best Login Method

Post by Apollo »

Sjwdavies wrote:So basically, the $passwordHash would look like: passwordHashed . constant(salt) . unixTimestampHashed?
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), then

$passwordHash = hash('sha512', $password.$salt.$unixTimeStamp );

And $passwordHash is stored in the user database.
Sjwdavies wrote:So you'd do something like

Code: Select all

set_cookie('loggedIn', hash('sha512' , $passwordHash.$_SERVER['REMOTE_ADDR'].$someOtherSalt.$userPepper ));
Not exactly, my cookie string looks like this:

"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).
Post Reply