1

With a multi-user site, how strict should I verify my users' passwords?

I've searched around a little bit, and I've only found questions about how to verify user passwords. But I know how to create salted hashes for passwords to store in a database (PHP's password_hash()), and I know how to verify those passwords (PHP s password_verify()).

I'm asking what types of restrictions I should put on user passwords on my site. Because passwords are never shown on a webpage, should I put strict restrictions on them like the usernames?

I know that usernames are shown, and are vulnerable to XSS attacks (which I've prevented against for usernames), but passwords are different, and can't be hacked this way (I think this is how it works; correct me if I'm wrong).

I know that passwords are often personal and very unique. I don't know if I should restrict special characters that could make a password more secure, including special characters similar to those in an XSS attack.

I'm asking if any password should be allowed (within certain character limits); if not, then what is a recommended (secure) method?

Jonathan Lam
  • 16,831
  • 17
  • 68
  • 94
  • 2
    I think you might get better answers on either http://security.stackexchange.com/ or http://ux.stackexchange.com/, albeit from different points of view. In my experience, password restrictions are almost always frustrating for users. My advice would be to avoid passwords altogether. Use a [federated identity](http://en.wikipedia.org/wiki/Federated_identity) from elsewhere, or [no password](https://nopassword.alexsmolen.com/). If you must have a password, use a strength meter, but leave it up to the user. – kojiro Jan 19 '15 at 16:11
  • @kojiro is there a way I could transfer this question? – Jonathan Lam Jan 19 '15 at 16:13
  • A moderator might be able to move it for you. You could flag it for moderator attention and ask, or just ask on meta.stackoverflow.com. (Never fear asking the mods for help – there's no stigma with flagging your own question.) If not, you could close it here and open it elsewhere. As always, read the [security.se help](http://security.stackexchange.com/help/on-topic) and [ux.se help](http://ux.stackexchange.com/help/on-topic) to see if your question is a good fit. – kojiro Jan 19 '15 at 16:17

2 Answers2

1

First, the password strength.
This is important to prevent password guessing or brute force attack. The stronger a password is — the better, of course. You can limit it to minimum 10 characters for example and require digits and upper case characters in it. That's quite strong already, but you can also require the use of symbols like !, $, @, #, etc. That password would be very secure.

As for storing the password securely — this is a different topic — and you should never store or show a password in open form. Always hash them with, for example:

$password = password_hash($password, PASSWORD_DEFAULT);

And store the resulting string in the database.
This is considered top secure today.

To check if an entered password is correct, all you need to do is use the function password_verify(), to compare the entered password with the stored hashed one.

$success = password_verify($entered_password, $hash_stored_in_mysql);

$success will become true or false, that's all you need to know if passwords match or not.

So good to have this password_hash and password_verify today, people used so many stupid and wrong ways to hash or encrypt passwords before this helpful functions were added!

Oleg Dubas
  • 2,320
  • 1
  • 10
  • 24
  • This answer is good on security, but troubling on usability. (This is why I marked this question as _opinion-based_.) The problem with that approach is that as soon as users get frustrated with security measures and see them as a hindrance they start looking for workarounds. Taping the password under the keyboard is a famous example. – kojiro Jan 19 '15 at 17:36
  • @kojiro, _opinion-based_ does not mean I am wrong :) You can allow entering 3-characters long passwords consisting of only digits, like `111`, it's your choice. I didn't say "it will be *right*" or "*the only right way*", I said "this would be very secure". – Oleg Dubas Jan 19 '15 at 17:49
  • 1
    This could turn into one of those comment threads where each participant restates with increasing ferocity how much he never disagreed with the previous commenter in the first place. – kojiro Jan 19 '15 at 18:07
1

You should allow any characters in the ASCII character set (although you could allow unicode if you want to take on slightly more complexity, e.g. when using password strength meters). You should set a maximum length of 72 ASCII characters if using bcrypt, as the PHP implementation restricts the hashing to these characters only:

Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters

This is good, as some implementations impose greater restrictions on length (55 characters).

With Unicode this is more complicated too, as some characters may take up to 4 bytes. My recommendation: Stick to ASCII, passwords can be secure enough (>= 64 bits of entropy) as it makes things simpler and if your users are using password managers (which they should) most of these only support the ASCII character set.

XSS is only a problem if data is output to a page. Ideally your system should implement a policy that passwords are only ever input, never output (even in <input type="password" /> fields). This will enhance security of passwords long term.

Community
  • 1
  • 1
SilverlightFox
  • 32,436
  • 11
  • 76
  • 145