If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

I use a different password/username for everything There may be one or two old exceptions to that, but I like to use something different every time I register some place. Hackers like to attack any weak security. If they can attack your site, even if it is the most generic site in the world, they will and repurpose it into whatever they want.

How would you use cookies to save a successful login so that the user can stay logged in even after leaving the site using crypt()? I'm sure the solution will come to me if I think on it a while. I figure that the password is not saved in the cookie in plain text, but using crypt is not making sense either. With md5 it was a lot simpler.

It just seems to me that it would not work to store the password in the database in crypt() format. It would have to be something like md5.

Well from my knowledge and workings, you can do a persistent login with cookies but you would need to re-verify the person when they come back to the site to make sure they are who they say they are. I personally set at cookie for their username and another for their unique id in the db. I don't put their password either plain or hashed in the cookie so that they can't take their known password and the hash and do a reverse crack to figure out the algorithm steps I take. Then when they come back to the site I validate those cookies against the database and then turn everything over to sessions while they are there so they can't do more poking on the security once they arrive. Some sites also validate the IP but that is a little too much for the normal site to worry about cause so many people use mobile devices now that the IP is constantly changing.

I have found and read many of the tutorials for login systems and most if not all really don't do a excellent job of it securely. On my sites I have it re-validate the session even after 30 minutes of inactivity and store all passwords in a hash() whirlpool plus salt and unique salt to the user.

In my opinion, checking the username and user id from the cookies is pretty fool proof as long as you also have the db secured against sql injection cause user names and user ids will always be unique to one person and any trying to get a different combination will simply fail unless they just truly get lucky with the combination. I also require strong passwords with at least one capital letter, at least 7 characters long and at least one number.

Honestly a person could go on and on about this subject but if you take the normal precautions you will be fine. If your site gets big then by all means drastically improve your security so you don't become another victim of those rogue sites that deliberately attack sites just to show people they could, they do have some pretty smart people working there. My understanding is that Facebook uses O-Auth or something like that, that they developed I think, it is said to be very very secure and there are tutorials out there on how to login a person through the system as long as they have a facebook account. In that instance they are using their o-auth to do all the validation.

Traq, interesting points. Makes sense to me. I think you missed my point about not knowing the algorithm, though. Let's say you use md5(md5(string)) (or anything else). Short of actually recursively unencrypting (via lookup tables), there's no way to work out what the original password is. The only reason that isn't very strong is because it's just using md5 on a loop. It seems very easy to me to create a unique/unknown hashing algorithm. For example, let's say this: md5(string) then reverse the first and last characters of that resulting string. Now, unless someone hacks your server and can see your algorithm they will never* figure out what you're doing. (*You'd actually have to make it less transparent than that-- if they had a password and a hash, then they could work out by just guessing that you did what I described. But if you make it a little less visually obvious, then what I said holds.)

Is this not true? Can you think of any reason that doesn't make sense?

Admittedly, there is one problem: if someone hacks your site, and some of your users use these passwords on other websites, then by hacking your site and working all of this out, the passwords will be compromised for all sites they're used on. But that's the users' fault anyway.

James, you should never allow the hash to give direct access to the account. If you do that, then it becomes the password and there is no decrypting necessary-- they can manually set the cookie to that value (assuming they can get their hands on the hash) and then they will have access.

There are two possibilities as I see it:
1. Use a weaker intermediate hash as a client-side somewhat non-secure login token stored in a cookie. This would then AGAIN go through hashing on the server (for the original point of it), but it would already be hashed on the client's machine so the password could not be read directly. However, aside from privacy concerns, this is actually as non-secure as just storing the password itself in a cookie-- that hash will still allow someone else access to the site. Probably best to avoid this.

2. Don't store the password or the hash anywhere. Upon logging in (that is, when the user submits a password that generates a hash matching the hash on file), then you would create a session (or database entry) and store a value for that user to be logged in. It can be as simple as $loggedin= 1; (or realistically, in a DB query or $_SESSION['loggedin'] = 1;), along with whatever account it is associated with (or if you prefer use the User ID as the value of that variable). Do not store that on the client side obviously, because they could fake that. Store it securely on the server-- the user never sees it (and by the way, unless you print/echo it, sessions are hidden from the user, so that's fine, short of the server being hacked).
Now, the login is based on the session (or DB entry). You will need to still connect the user to that session (or DB entry) and this can be done with a cookie (or by other things like remembering the IP address, but cookies are the most common and probably best way). And sessions automatically make those cookies for you, so you're set.

There is still a security concern-- if someone steals the session ID cookie from your computer, they can steal your session-- they'll be temporarily logged in as you. However:
1. That only lasts as long as that session. (Note that you wouldn't want to allow direct access to changing your password without re-inserting the old password for this reason!!)
2. You can try to prevent this by using HTTPS.
3. You can blame the user for getting hacked, and it's only for one session anyway.
4. You can require the same IP address for that session, if you'd like. The downsides: i) a network would share an IP address, so a hacker in a coffee shop would still be able to gain access with that session ID; ii) the user will need to keep logging in repeatedly if they're changing IP addresses-- this is rarely relevant but can be for mobile users who are switching between wifi and mobile networks often.
5. The password itself is never stolen or visible, and they cannot control how long that session ID is valid for-- if you can somehow catch this, you could stop it immediately, and the whole time the password is still secure and the user can just log in again. (This is one reason, I think, that banks and so forth automatically log you out after inactivity-- it just makes it all that much harder for someone to steal your session and do anything with it.)

Last edited by james438; 01-26-2013 at 02:05 AM.
Reason: disabled the smilies

The cookies used on my site are all tied to their ip address, which is stored in the database and updated every time the user logs in. I find that tying cookies to ip addresses is very handy because if I log in to my site on my home computer, but forget to log out of my friend's computer that I was visiting earlier in the day the cookie on my friend's computer will no longer work.

I've done that on sites before and I like it. I'm a bit hesitant due to mobile users, and there's the thought that multiple users behind one IP are still non-secure, but overall it seems at least beneficial (if not perfect) in many cases. It's a tradeoff of how many times you require users to log in and how much security you want. Often it makes sense, I think.

For the record, you could also impose a 20 minute or 3 hour or 5 day limit on the access regardless of IP, if this is a truly high security website. (That could be extended with activity, or not.)

How would you use cookies to save a successful login so that the user can stay logged in even after leaving the site using crypt()? I'm sure the solution will come to me if I think on it a while. I figure that the password is not saved in the cookie in plain text, but using crypt is not making sense either. With md5 it was a lot simpler.

Don't store the hash (or password, or anything related to it). It shouldn't be exposed, and it's unnecessary anyway.

If they're already logged in, all you need is a unique identifier: the session id works just fine (even if you don't store any info with it).
Set the session cookie to expire some amount of time in the future, and store the id in the DB. You could even store their old session along with it and pick up where they left off.

In short, you're not really using the cookie, or the info it contains, for authentication - you're just making the user's session longer, and interruptable.

Which brings up another good practice - whenever a user tries to perform a sensitive action, you re-authenticate. If they want to view their user cp, and didn't log in _this_ session, they need to confirm their password. If they want to change their email or password, they need to confirm their current password "no matter what."

Originally Posted by james438

It just seems to me that it would not work to store the password in the database in crypt() format. It would have to be something like md5.

I'm not sure how you mean. Whatever algorithm you use with crypt() will give you a hash (of some length), just like md5 does.

Originally Posted by fastsol1

Well from my knowledge and workings, you can do a persistent login with cookies but you would need to re-verify the person when they come back to the site to make sure they are who they say they are. I personally set at cookie for their username and another for their unique id in the db.

There's no real reason to set two cookies. If one is stolen, it's all but certain the other was also.

How do you verify them (or do you just mean you check the id in the cookie against the DB record)?

Originally Posted by fastsol1

I don't put their password either plain or hashed in the cookie so that they can't take their known password and the hash and do a reverse crack to figure out the algorithm steps I take.

Absolutely.

Originally Posted by fastsol1

In my opinion, checking the username and user id from the cookies is pretty fool proof as long as you also have the db secured against sql injection cause user names and user ids will always be unique to one person and any trying to get a different combination will simply fail unless they just truly get lucky with the combination.

instead of giving them the user id and name, give them a token (e.g., hash the user name and id). If you're going to give out the user id in a cookie, you have to assume that it will eventually be leaked - and therefore, can't be trusted for authentication. If you hash the username+id, you might add another unique value to the mix - say, the timestamp when they logged in and/or the browser's AU string. That way, it'll be harder to guess what the hash is composed of (since, every time they log in, the hash in the cookie will change).

Originally Posted by fastsol1

I also require strong passwords with at least one capital letter, at least 7 characters long and at least one number.

These sorts of requirements can be self-defeating: an attacker can narrow the list of possible passwords if they know that they must contain characters of certain classes. A minimum length, absolutely - but "at least one of" and "one of" makes it harder for the user to remember the password, too. I always recommend passphrases, but there's no way to "enforce" any of this without causing more problems.

Originally Posted by fastsol1

Honestly a person could go on and on about this subject but if you take the normal precautions you will be fine.

Agreed - "normal" meaning "reasonable," of course; not "typical."

Originally Posted by fastsol1

... using their o-auth to do all the validation.

OAuth isn't an authentication tool, itself, it's a protocol for allowing third-party authentication (it's for trusting someone else to authenticate). It can be implemented with any login system, really. FB, twitter, most big players implement it.

Originally Posted by djr33

I think you missed my point about not knowing the algorithm, though... let's say this: md5(string) then reverse the first and last characters of that resulting string. Now, unless someone hacks your server and can see your algorithm they will never* figure out what you're doing.

Of course - in this case, we're talking about "making it difficult" to crack stolen hashes (i.e., limiting/delaying damage from a successful break-in). If someone got your DB, they didn't necessarily get your site also, but it's a good bet.

Additionally, there's some contradictory wisdom:
...you should use stuff designed by people who know what they're doing, rather than trying to do it all yourself.
...if you use something designed by others, the attackers probably know about it (and better than you do) too.

Widely used software (like WordPress, Joomla, etc.) has this disadvantage.

Originally Posted by djr33

James, you should never allow the hash to give direct access to the account. If you do that, then it becomes the password and there is no decrypting necessary-- they can manually set the cookie to that value (assuming they can get their hands on the hash) and then they will have access.

Right. You can use a "logged in" token to recognize the user (who they're claiming to be), but not to authenticate them (prove who they are).

Good article, for the most part. I don't claim to be a crypto expert (more like a passive enthusiast or something), but a few things in that article don't strike me right.

First off, his attack on "double-hashing" contradicts most advice I've heard anywhere, some of it from people I consider authoritative. "Stretching" is usually considered indispensable for creating "difficult" hashes.

His argument about increasing the probability of a collision doesn't quite make sense, either: if you increase the odds from 1 / (n) to 1 / (n/2), and so forth, by extension you'll eventually reach 1 / (n/n)... essentially, the point where *any* password will match any other password. While that may statistically (eventually) (maybe?) be true, I don't see it as a practical concern. (I think -not 100% sure- that this doesn't hold up anyway: it's like buying 100,000 lottery tickets for consecutive drawings. It doesn't increase your odds. Each time, you're back to square one.)

(Speaking of the lottery, do you know just how big nis? Even with SHA-1, collisions are *highly* unlikely.

A higher probability exists that every member of your programming team will be attacked, and killed, by wolves, in unrelated incidents, on the same night.

I forget where I read that, but it's real statistics. In any case, the author contradicts himself later on:

Originally Posted by firedart

PBKDF2 (Password-Based Key Derivation Function v2)
Works off MD5, however this takes the current text and re-hashes thousands of times using md5. So it's actually really good, ...

This thread has become more involved than I originally intended, but it has increased my understanding of hashing and passwords. I have a few ideas now on how I want to improve security on my site. Namely I'll be creating my own hash that is a variant of one of the currently used hashes out there, keep using ip addresses as I have been, stop storing hashed passwords in cookies, and one or two other things that would be best left unmentioned.

James, I haven't tried it, but I can't imagine it is supposed to give different results. I'd suggest checking over that script in some detail. The PHP.net page gives some examples including specifying which algorithm you're using, and that might be important. Admittedly that's one of the most confusing explanations I've seen for a function because it has so many non-argument parameters.

Traq, I looked over that article (only) to check on the potential problem of double-hashing. I'm quite confused by it too. But I think there's a point. Here's how I see it:

--Benefits of double-hashing (or similar techniques):
It means you're getting unique hashes (or at least they're less common). Hopefully those hashes aren't out there floating around in a database somewhere. For this reason, it makes more sense to me to do some weirder things that just double hashing (perhaps, in the middle of it, reverse some characters in the string, or whatever you want). In short, it just adds layers that would need to be unlayered/decrypted for anyone to track it. It also is a serious advantage with them not knowing your algorithm (but don't use just md5(md5()), haha, since that's obvious).

--Problems of double-hashing or more:
Every non-initial iteration has the same kind of input, a hash. Assuming that similar inputs generate similar hashes*, the odds of two hashes giving the same output hash are higher than that of two unrelated passwords in the first place. Therefore, "collisions" themselves aren't the problem, but that there will be multiple original passwords that could give you access. With brute force, that just means that it's relatively faster to find a password that happens to work, even if it isn't the same one originally entered by the user-- but because of the collisions it still looks the same to your server.
(*I have to assume that this is part of the concern. If two almost identical inputs are NOT more likely to give identical hashes than two completely unrelated inputs, then I can't see why this would be less secure in that sense. A perfect hashing algorithm would give completely unrelated results. But maybe the algorithms aren't perfect?)
Alternatively, there's another possibility, which might be what they were focusing on in the link. By iterating the algorithm many times, the odds increase that one of the loops generates the same hash as a previous loop. If that happens, then there will be an infinitely repeating pattern. (Think back to long division, where eventually the numbers began to repeat and you could stop because you knew it would keep repeating.) Regardless, I'm not sure why this would be less secure that only one iteration, although it may be asymptotically less beneficial to add more and more iterations. (Maybe if there might be any sort of unbalanced nature to the algorithms (one output is more probable than another) this could eventually lead to potential collisions and many inputs with the same output.)

Beyond that, my brain can't really handle working out the probabilities at the moment.

From another perspective there is a legitimate (theoretical, not practical) concern here-- by re-hashing, you are limiting it to the 16^32 possible inputs that hashes might be. Therefore, that's fewer than the N^L (N=possible symbols; L=length) passwords that could have been used. So on purely mathematical grounds, there are fewer possible inputs, fewer possibilities for brute force, etc. The problem with this concern is that 16^32 is a huge number! And even if that's not "enough", then we have to concede that most passwords are less than 32 characters anyway. The result is something like 100 symbols with maybe up to 16 places = 100^16. That's 1e32, and 16^32 is 3.4e38. Admittedly, the possibility of using 100 characters is helping the shorter passwords come somewhere near the scale of how many possible hashed strings there are, but it's still 6 powers of ten away-- that's like one million compared to one. The point is... although it's "limited" in a theoretical sense, it's still plenty big for the real world.
A similar issue is that of using sha1(md5(x)). Sure, using md5() in there limits the amount of information going into sha1(). But it's still as powerful as the original md5(). It's not LESS powerful than the md5().

Basically... there are some mathematical issues here and if you started to iterate thousands of times you might find that the more iterations were each less and less effective. But I don't see any of this actually compromising the hash so that it's worse than only hashing once. The only way that would be the case is if the hashing algorithms are not properly distributed and some results are more likely than others. But still, that would probably only cause issues at very large numbers of iterations.

Traq, as you said the odds do go way up as you repeat more times that you would eventually happen to land on the right hash somewhere in the iterations. But the way for it to actually work is to land on the right hash at the end of the iterations. I don't see how having the right hash after 50 iterations would be at all helpful for you to find the right one after 100. It might seem like you're "close" if you did get the right hash at the wrong time, but when you actually try to use that to access the server, the server won't care that it's close at one point in time-- it'll just check the last value, which likely won't be that one. The weakness would only apply if looping began to occur, which again only would happen if it was a badly designed hashing algorithm, I think. (Technically it might necessarily loop, but that's going to be after probably billions of iterations.)